Compter le nombre total de fichiers dans un répertoire particulier avec une extension spécifique

32

Je veux compter le nombre total de fichiers dans un répertoire particulier qui se termine par l'extension ".mp4".

J'obtiens la commande suivante:

ls -F |grep -v / | wc -l

Il compte tous les fichiers dans un répertoire particulier, mais je veux le nombre de fichiers se terminant par l'extension .mp4.

Existe-t-il une commande Ubuntu pour cela?

Prakash V Holkar
la source
2
La réponse simple, correcte et directe est @ louis-matthijssen one. ls -1la gestion des caractères de nouvelle ligne rend, dans ce cas, raisonnable l'analyse de la lssortie. Celui marqué est incorrect pour l'utilisation de l'indicateur -R.
Rmano

Réponses:

19

Ici, vous pouvez faire de cette façon

ls -lR /path/to/dir/*.jpg | wc -l

Cela vous donne le compte

sk1712
la source
5
Pourquoi -R? Pourquoi faire un plein statquand vous avez juste besoin du nom de fichier? Pourquoi ne pas ls -1 *.jpg| wc -l? (ok, ne fonctionne pas si vous avez des noms de fichiers avec des retours à la ligne. Dans ce cas, vous le méritez ;-) ...)
Rmano
2
... et la question était de "compter le nombre de fichiers dans un répertoire". De plus, cela listera récursivement tout le contenu des sous-répertoires dont le nom se termine par .jpg , et non les fichiers des sous-répertoires se terminant par .jpg. L'avez-vous déjà testé?
Rmano
1
La question dit "fichiers dans un répertoire spécifique", ce qui implique que la récursivité du sous-répertoire n'est pas souhaitée.
David Richerby
1
Cela échoue également s'il y a trop de fichiers dans le répertoire (car il *.jpgest développé par le shell, pas par ls) et s'il y a des fichiers dont les noms commencent par des tirets.
David Richerby
2
@DavidRicherby Ceci ignore les noms commençant par .. Mais cela fonctionne bien avec les tirets dans les noms, sauf quand /path/to/dirla chaîne vide ou un chemin relatif commençant par un trait d'union. Mais j'avais tort avant d'avoir dit que lsremplace les caractères par ?. Cela se produit lorsque stdout est un terminal, mais ici, la sortie est un canal, donc lsenvoie tous les caractères des noms de fichiers vers wc. Cela rend cette réponse incorrecte sans l' indicateur -qou -bpour modifier ce comportement , car les noms de fichiers peuvent contenir des sauts de ligne. La réponse de l0b0 est exempte de ces problèmes.
Eliah Kagan
42

Malheureusement, ce problème bénin est difficile à résoudre d'une manière qui prend en charge tous les noms de fichiers et est portable. C'est sûr (il gère les fichiers cachés, les chemins contenant des espaces, des tirets et même des nouvelles lignes) et compatible POSIX :

find /path/to/directory -mindepth 1 -type f -name "*.mp4" -printf x | wc -c

Si vous ne voulez pas que ce soit récursif, ajoutez simplement -maxdepth 1.

Vous ne devez pas analyser la lssortie.

Tester:

$ cd -- "$(mktemp -d)"
$ touch -- -foo.mp4 .bar.mp4 .bat.mp4 'baz.mp4
> ban.mp4'
$ find . -mindepth 1 -type f -name "*.mp4" -exec printf x \; | wc -c
4

Comparez avec la réponse acceptée :

$ ls -lR ./*.mp4 | wc -l
3

Ou d'autres suggestions:

$ find . -name "*.mp4" | wc -l
5
$ ls -1 *.mp4 | wc -l
ls: invalid option -- '.'
Try 'ls --help' for more information.
0
$ find . -name "*.mp4" | wc -c # Answer fixed at a later time
51
$ find . -name "*.mp4" | wc -l
5
$ find . | grep -i ".mp4$" | wc -l
5
$ ls . | grep ".mp4$" | wc -l
3
l0b0
la source
2
Bien que cette réponse soit correcte et robuste, vous pouvez utiliser à la -printf xplace de -exec printf x \;. C'est-à-dire: il find /path/to/directory -mindepth 1 -type f -name "*.mp4" -printf x | wc -c n'y a pas besoin de -execla printfcommande externe , qui s'il y a beaucoup de fichiers sera très lente , car findelle doit fork (2) une copie d'elle-même et ensuite execve (2) /usr/bin/printf . Avec -exec printf x \;, cela doit être fait une fois pour chaque fichier .
Eliah Kagan
-printfn'est pas pris en charge dans POSIXfind , c'est pourquoi je ne l'ai pas utilisé.
l0b0
1
Ni -mindepthet -maxdepthque vous avez utilisés.
Eliah Kagan
Bon point, je n'avais pas compris ça!
l0b0
BSD findcontient -mindepthet -maxdepthmais ne contient pas, -printfdonc j'apprécie l'inclusion des deux.
Joseph
11

Celui-ci recherche, trie et répertorie tous les fichiers par extension dans l'ordre:

find . -type f | sed 's/.*\.//' | sort | uniq -c
squozen
la source
Excellent! Je voudrais juste ajouter un | sort -rnà la fin et peut-être un -mindepth 1dir si juste actuel.
Pablo A
Et peut-être un tuyau pour head -nobtenir le top n.
Raman
une si bonne réponse, merci beaucoup
Dennis Golomazov
5

Je pense que c'est très simple en suivant les commandes.

$ find . -name "*.mp4" | wc -l
8

ou

$ find . | grep -i ".mp4$" | wc -l
8

Je pense que les commandes ci-dessus calculent le nombre de noms de fichiers et de répertoires *.mp4

donc je vous suggère d'utiliser l' -type foption comme findparamètre comme suit.

$ find . -name "*.mp4" -type f | wc -l
8

En outre, ls -lRpeut être utilisé commefind .

xiaodongjie
la source
2

Vous pourriez utiliser ls -1 *.mp4 | wc -l.

Cela listera tous les fichiers se terminant par .mp4, imprimant chaque fichier sur une nouvelle ligne ( ls -1 *.mp4), wcdirigera la sortie vers laquelle comptera le nombre de nouvelles lignes en utilisant l' -lindicateur.

Louis Matthijssen
la source
Je ne sais pas pourquoi cela a été rejeté, cela fonctionne
Panther
Puisque *.mp4est développé par le shell, non ls, cela échouera s'il y a tellement de .mp4fichiers dans le répertoire que leur liste ne peut pas être passée lsen arguments.
David Richerby
@Rmana Testez-le dans un répertoire contenant un fichier appelé--.mp4
David Richerby
@DavidRicherby oui, vous avez raison. --résoudra le deuxième cas; le premier affichera un message d'erreur (vous avez besoin de beaucoup de fichiers!) et une autre belle question ici. Des cas d'angle, mais qui valent la peine d'être remarqués, oui.
Rmano
1
@Rmano Sans ajouter -qou -b, cela ne tolère pas les retours à la ligne dans les noms de fichiers. Si vous exécutez à ls -1 *.mp4partir de votre terminal sans tuyau, lsvoit sa sortie standard est un terminal et prend -qcomme implicite, l'impression ?s. Mais ce comportement disparaît lorsque la sortie est canalisée. ls -1 *.mp4 | wc -lsurfacturations s'il y a des nouvelles lignes. ls -1 *.mp4 | catmontre ce que wc"voit". (De même, -1est implicite lorsque stdout n'est pas un terminal, il est donc facultatif.) ls -1q -- *.mp4 | wc -lFonctionne presque, mais pas avec zéro fichier .mp4.
Eliah Kagan
0

Cela devrait vous donner la liste des fichiers avec .mp4

ls /path/to/directory | grep ".mp4$"

Lorsqu'il est combiné avec wc -lvous donnera un compte

ls /path/to/directory | grep ".mp4$" | wc -l

si vous souhaitez que la recherche inclue des sous-répertoires

ls -lR /path/to/directory | grep ".mp4$" | wc -l
Retour.Slash
la source
ne donne pas de compte
Panther
me l'a donné lorsqu'il est utilisé avecwc -l
Back.Slash
utilisez ls sans piping pour grep et raccourcir votre réponse. Il a été publié au moins deux fois maintenant.
Panther
@ bodhi.zazen ls /directory/*.mp4amène le shell à étendre le glob et à exécuter quelque chose comme ls /directory/file1.mp4 /directory/file2.mp4 ...ceci échouera si le répertoire contient plus de fichiers mp4 que ce qui peut être passé en argument ls.
David Richerby
@DavidRicherby - ce n'est pas ma commande ls, j'utilise find;)
Panther
0

En bash, un recours à froid à l'utilisation de tableaux avec glob:

$ files=( *.mp4  )
$ echo ${#files[@]}
30
Sergiy Kolodyazhnyy
la source
0
ls | grep --count \.csv$

Remplacez (.csv par l'extension souhaitée)

Explication: Je pense qu'un schéma simple consiste à récupérer la liste des fichiers et à compter l'extension avec grep. \.pour correspondre .et $pour faire correspondre l'extension à la fin de la ligne. Cela fonctionne parce que lorsque la sortie de ls est canalisée, un nom de fichier est envoyé par ligne, que vous pouvez vérifier en exécutant:

ls | cat
Mohsin Raza
la source
1
Notez qu'au lieu de grep --count, vous pouvez également utiliser grep -c.
Mohsin Raza