Contar o número total de arquivos em um diretório específico com extensão específica

32

Quero contar o número total de arquivos em um diretório específico que termina com a extensão ".mp4".

Estou recebendo o seguinte comando:

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

Ele conta todos os arquivos em um diretório específico, mas quero a contagem de arquivos que terminam com a extensão .mp4.

Existe algum comando do Ubuntu para isso?

Prakash V Holkar
fonte
2
A resposta simples, correta e direta é @ louis-matthijssen one. ls -1o manuseio de caracteres de nova linha torna, nesse caso, sensato analisar a lssaída. O marcado está errado para o uso do sinalizador -R.
Rmano

Respostas:

19

Aqui você pode fazer assim

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

Isso lhe dá contar

sk1712
fonte
5
Por que o -R? Por que fazer um full statquando você só precisa do nome do arquivo? Por que não ls -1 *.jpg| wc -l? (ok, não funciona se você tiver nomes de arquivos com novas linhas na mesma Nesse caso, você merece isso ;-) ....)
Rmano
2
... e a pergunta era "contando o número de arquivos em um diretório". Além disso, isso listará recursivamente todo o conteúdo dos subdiretórios cujo nome termina em .jpg , não os arquivos nos subdiretórios que terminam em .jpg. Você já testou?
Rmano
1
A pergunta diz "arquivos em um diretório específico", o que implica que a recursão do subdiretório não é desejada.
David Richerby
1
Isso também falha se houver muitos arquivos no diretório (porque *.jpgé expandido pelo shell, não por ls) e se houver arquivos cujos nomes começam com hífens.
David Richerby
2
@DavidRicherby Ignora os nomes que começam com .. Mas na verdade funciona bem com hífens nos nomes, exceto quando /path/to/dira string vazia ou um caminho relativo começa com um hífen. Mas eu estava errado antes de dizer que lssubstitui caracteres por ?. Isso acontece quando stdout é um terminal, mas aqui a saída é um canal, então lsenvia todos os caracteres dos nomes de arquivos para wc. Isso faz com que esta resposta esteja errada sem o sinalizador -qou -bpara alterar esse comportamento , porque os nomes de arquivos podem conter novas linhas. A resposta de 10b0 está livre desses problemas.
Eliah Kagan 10/10
42

Infelizmente, esse problema benigno é difícil de resolver de uma maneira que suporta todos os nomes de arquivos e é portátil. Isso é seguro (ele lida com arquivos ocultos, caminhos contendo espaços, traços e até novas linhas) e compatível com POSIX :

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

Se você não quiser que seja recursivo, basta adicionar -maxdepth 1.

Você não deve analisar a lssaída.

Teste:

$ 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

Compare com a resposta aceita :

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

Ou outras sugestões:

$ 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
fonte
2
Embora essa resposta seja correta e robusta, você pode usar em -printf xvez de -exec printf x \;. Isto é: find /path/to/directory -mindepth 1 -type f -name "*.mp4" -printf x | wc -c Não há nenhuma necessidade para -execo externo printfcomando, que se houver muitos arquivos será muito lento , porque findtem que fork (2) fora de uma cópia de si mesmo e, em seguida, execve (2) /usr/bin/printf . Com -exec printf x \;, isso deve ser feito uma vez para cada arquivo .
Eliah Kagan 10/10
-printfnão é suportado no POSIXfind , razão pela qual não o usei.
L0b0
1
Nem são -mindepthe -maxdepth, que você usou.
Eliah Kagan 11/11
Bom ponto, eu não tinha entendido isso!
L0b0
O BSD findcontém -mindepthe -maxdepthnão contém, -printfentão eu aprecio a inclusão de ambos.
Joseph
11

Este encontra, classifica e lista todos os arquivos por extensão em ordem:

find . -type f | sed 's/.*\.//' | sort | uniq -c
squozen
fonte
Excelente! Eu apenas adicionaria um | sort -rnno final e talvez um -mindepth 1se apenas atual.
Pablo A
E talvez vá para head -no topo n.
Raman
resposta tão boa, muito obrigado
Dennis Golomazov
5

Eu acho que é muito simples como seguir os comandos.

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

ou

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

Eu acho que os comandos acima calculam a contagem de nomes de arquivos e diretórios *.mp4

então eu sugiro que você use a -type fopção como findparâmetro da seguinte maneira.

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

Além disso, ls -lRpode ser usado comofind .

xiaodongjie
fonte
2

Você poderia usar ls -1 *.mp4 | wc -l.

Isso listará todos os arquivos que terminam em .mp4, imprimindo cada arquivo em uma nova linha ( ls -1 *.mp4), canalizando a saída na wcqual contará o número de novas linhas usando o -lsinalizador.

Louis Matthijssen
fonte
Não sei por que isso foi downvoted, ele funciona
Panther
Como *.mp4é expandido pelo shell, lsisso não ocorrerá se houver tantos .mp4arquivos no diretório que a lista deles não possa ser transmitida lscomo argumento.
David Richerby
@Rmana Teste lo em um diretório que contém um arquivo chamado--.mp4
David Richerby
@DavidRicherby sim, você está certo. --resolverá o segundo caso; o primeiro apresentará uma mensagem de erro (você precisa de muitos arquivos!) e outra boa pergunta aqui. Casos de canto, mas vale a pena notar, sim.
Rmano
1
@Rmano Sem adicionar -qou -b, isso não tolera novas linhas nos nomes de arquivos. Se você ls -1 *.mp4sair do terminal sem tubulação, lsvê que o stdout é um terminal e assume -qcomo implícito, a impressão de ?s. Mas esse comportamento desaparece quando a saída é canalizada. ls -1 *.mp4 | wc -lsuperconta se houver novas linhas. ls -1 *.mp4 | catmostra o que wc"vê". (Da mesma forma, -1está implícito quando stdout não é um terminal, portanto é opcional.) ls -1q -- *.mp4 | wc -lQuase funciona, mas não com zero arquivos .mp4.
Eliah Kagan 11/10
0

Isso deve fornecer a lista de arquivos com .mp4

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

Quando combinado com wc -llhe dará a contagem

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

se você deseja procurar incluir subdiretórios

ls -lR /path/to/directory | grep ".mp4$" | wc -l
Back.Slash
fonte
não conta
Panther
deu-me quando usado comwc -l
Back.Slash
use ls sem canalizar para grep e encurtar sua resposta. Foi postado pelo menos duas vezes agora.
Panther
@ bodhi.zazen ls /directory/*.mp4faz com que o shell expanda o globo e execute algo como ls /directory/file1.mp4 /directory/file2.mp4 ...Isso falhará se o diretório contiver mais arquivos mp4 do que os que podem ser passados ​​como argumentos ls.
David Richerby
@DavidRicherby - não é comandar meus ls, eu uso encontrar;)
Panther
0

No bash, um recurso frio para usar matrizes com glob:

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

Substitua (.csv pela extensão desejada)

Explicação: Eu acho que um esquema simples é buscar a lista de arquivos e contar a extensão com grep. \.para corresponder .e $corresponder à extensão no final da linha. Funciona porque quando a saída de ls é canalizada, um nome de arquivo é enviado por linha, que você pode verificar executando:

ls | cat
Mohsin Raza
fonte
1
Observe que, em vez de grep --count, você também pode usar grep -c.
Mohsin Raza 22/06