Contando recursivamente arquivos em um diretório Linux


728

Como posso contar recursivamente arquivos em um diretório Linux?

Eu achei isto:

find DIR_NAME -type f ¦ wc -l

Mas quando executo isso, ele retorna o seguinte erro.

find: os caminhos devem preceder a expressão: ¦


64
Você está confundindo a barra quebrada ¦(ASCII 166) com a barra vertical |(ASCII 124) usada para o pipeline UNIX .
Skippy le Grand Gourou

7
@SkippyleGrandGourou Não é chamado de pipe?
precisa saber é o seguinte

27
@ DaveStephens Sim, também é chamado assim. Também é chamado de golpe de Sheffer, barra vertical, barra vertical, barra vertical, barra vertical, barra, obelisco, glidus.
emlai

64
@zenith Acabei de chamá-lo de Bob.
Christopher

15
Na RFC20 é chamada "linha vertical". "Pipe" é o nome do operador de shell, e não o nome do símbolo. Assim como *o caractere ASCII "asterisco", mas "vezes" em alguns outros contextos.
magro

Respostas:


1327

Isso deve funcionar:

find DIR_NAME -type f | wc -l

Explicação:

  • -type f para incluir apenas arquivos.
  • |( e não¦ ) redireciona finda saída padrão do wccomando para a entrada padrão do comando.
  • wc(abreviação de contagem de palavras) conta novas linhas, palavras e bytes em sua entrada ( documentos ).
  • -l para contar apenas novas linhas.

Notas:

  • Substitua DIR_NAMEpor .para executar o comando na pasta atual.
  • Você também pode remover os -type fdiretórios para incluir (e links simbólicos) na contagem.
  • É possível que esse comando conte em excesso se os nomes de arquivos puderem conter caracteres de nova linha.

Explicação do motivo pelo qual seu exemplo não funciona:

No comando que você mostrou, você não usa o "Pipe" ( |) para conectar dois comandos, mas a barra quebrada ( ¦) que o shell não reconhece como um comando ou algo semelhante. É por isso que você recebe essa mensagem de erro.


27
O fem -type fsignifica arquivos e wc -llinhas de contagem de palavras.
Serge Stroobandt

3
Remova a -type fincluir diretórios na contagem
phatblat

3
Não há necessidade da -printbandeira
Zoltán

3
Se houver alguma possibilidade de que os nomes de arquivo contenham o caractere de nova linha, convém usar o -print0sinalizador.
gaboroncancio

2
@gaboroncancio Isso não vai ajudar, a menos que alguma implementação de wctenha uma opção para ler uma lista terminada nula. Veja minha resposta para uma alternativa.
Reinstate Monica Please

100

Para o diretório atual:

find -type f | wc -l

5
Esta solução não leva em consideração o nome do arquivo que contém novas linhas.
Kusalananda

2
Para o diretório atual, você nem precisa do.
baptx

1
Na verdade, em algumas plataformas, você não precisa explicitarfind .
tripleee

1
@Kusalanandra Seu comentário se aplica a quase todas as respostas aqui.
tripleee

69

Se você deseja obter uma análise detalhada de quantos arquivos existem em cada diretório abaixo do diretório atual:

for i in */ .*/ ; do 
    echo -n $i": " ; 
    (find "$i" -type f | wc -l) ; 
done

Isso pode ir tudo em uma linha, é claro. Os parênteses esclarecem a saída de quem wc -ldeveria estar assistindo ( find $i -type fneste caso).


7
Pode ficar preso em diretórios com espaços em seus nomes. Alterando a primeira linha para find . -maxdepth 1 -type d -print0 | while IFS= read -r -d '' i ; docorrigi-lo. Consulte Como posso ler um arquivo (fluxo de dados, variável) linha por linha (e / ou campo por campo)?
Arch Stanton

4
Usar findo loop externo é apenas uma complicação desnecessária. for i in */; do`
tripleee 12/06

função countit {para i em $ (encontre. -maxdepth 1 -type d); do file_count = $ (encontre $ i-tipo f | wc -l); eco "$ file_count: $ i"; feito }; countit | sort -n -r
Schneems

Finalmente, era disso que eu precisava. Minhas pastas têm milhares de arquivos para imprimi-los com a árvore ou qualquer outra coisa não é uma opção
lesolorzanov

Isso inclui ../ e não parece avançar - o que significa que não é regressivo.
Daniel Lefebvre

50

Você pode usar

$ tree

depois de instalar o pacote em árvore com

$ sudo apt-get install tree

(em uma máquina Debian / Mint / Ubuntu Linux).

O comando mostra não apenas a contagem dos arquivos, mas também a contagem dos diretórios, separadamente. A opção -L pode ser usada para especificar o nível máximo de exibição (que, por padrão, é a profundidade máxima da árvore de diretórios).

Arquivos ocultos também podem ser incluídos, fornecendo a -aopção


4
Esta é realmente a maneira mais simples de ver o número de diretórios e arquivos.
Lorem Ipsum Dolor

11
Na página do manual: por padrão, a árvore não imprime arquivos ocultos . Você precisa fornecer a -aopção de incluí-los.
eee

3
Para instalar isso no macOS, use brewe execute brew install tree, de preferência após a execução brew update.
Ashish Ahuja

4
Também está imprimindo todos os nomes de arquivos, por isso será lento se você tiver muitos arquivos.
Franck Dernoncourt

2
Uau, ferramenta muito boa, ele pode imprimir pastas coloridas, listar apenas pastas, produzir como JSON. Ele pode listar 34k pastas e 51k arquivos em poucos segundos. Olé!
brasofilo 10/01/19

46

No meu computador, rsyncé um pouco mais rápido do que find | wc -lna resposta aceita:

$ rsync --stats --dry-run -ax /path/to/dir /tmp

Number of files: 173076
Number of files transferred: 150481
Total file size: 8414946241 bytes
Total transferred file size: 8414932602 bytes

A segunda linha tem o número de arquivos, 150.481 no exemplo acima. Como bônus, você também obtém o tamanho total (em bytes).

Observações:

  • a primeira linha é uma contagem de arquivos, diretórios, links simbólicos etc. todos juntos, por isso é maior que a segunda linha.
  • a opção --dry-run(ou -nabreviada) é importante para não transferir os arquivos!
  • Usei a -xopção para "não cruzar os limites do sistema de arquivos", o que significa que se você executá-lo /e tiver discos rígidos externos conectados, ele contará apenas os arquivos na partição raiz.

Eu gosto da sua ideia de usar o rsync aqui. Eu nunca teria pensado nisso!
Qeole 3/08/16

Obrigado @Qeole, a idéia não é minha. Eu li isso há alguns anos atrás, em algum lugar em que o rsync é o mais rápido para excluir uma pasta com muitos arquivos e subpastas, então pensei que poderia ser rapidamente contar arquivos também.
Psd #

1
Tentei isso. Depois de executar as duas vezes anteriormente para preencher o cache fs, find ~ -type f | wc -ldemorou 1,7 / 0,5 / 1,33 segundos (real / usuário / sys). rsync --stats --dry-run -ax ~ /xxxdemorou 4,4 / 3,1 / 2,1 segundos. Isso é para cerca de 500.000 arquivos no SSD.
magro

Não sei qual a versão do rsync que você usou, mas no 3.1.2 é um pouco mais fácil de ler:Number of files: 487 (reg: 295, dir: 192)
mpen

Eu usei o rsync padrão no macOS:rsync version 2.6.9 protocol version 29
psmith

20

Como os nomes de arquivos no UNIX podem conter novas linhas (sim, novas linhas), wc -lpodem contar muitos arquivos. Eu imprimiria um ponto para cada arquivo e depois contaria os pontos:

find DIR_NAME -type f -printf "." | wc -c

1
Parece que esta é a única solução que lida com arquivos com novas linhas em seus nomes. Votado.
codeforester

2
hihi :) Adoro novas linhas de nomes de arquivos. Isso os torna apenas mais legíveis.
hek2mgl

Quero dizer, novas linhas nos nomes dos arquivos e não no conteúdo!
codeforester

1
Eu estava brincando ... Sim, novas linhas nos nomes de arquivos sempre precisam ser levadas em consideração. Eles podem vir de conteúdo malicioso ou menos espetacular, de um erro de digitação.
hek2mgl

18

Combinando várias das respostas aqui juntas, a solução mais útil parece ser:

find . -maxdepth 1 -type d -print0 |
xargs -0 -I {} sh -c 'echo -e $(find "{}" -printf "\n" | wc -l) "{}"' |
sort -n

Ele pode lidar com coisas estranhas, como nomes de arquivos que incluem parênteses de espaços e até novas linhas. Também classifica a saída pelo número de arquivos.

Você pode aumentar o número depois -maxdepthpara obter os subdiretórios também. Lembre-se de que isso pode levar muito tempo, principalmente se você tiver uma estrutura de diretórios altamente aninhada em combinação com um -maxdepthnúmero alto .


O que há com o echo -e? Eu acho que você o coloca para dobrar qualquer nova linha, mas também altera outros espaços em branco irregulares e tenta expandir qualquer caractere curinga presente literalmente nos nomes dos arquivos. Eu iria simplesmente com algo como find .* * -type d -execdir sh -c 'find . -type f -printf "\n" | wc -l; pwd'e viveria com quaisquer aberrações na saída, ou talvez brincasse com o Bash printf "%q"para imprimir o nome do diretório.
tripleee

10

Se você deseja saber quantos arquivos e subdiretórios existem no diretório de trabalho atual, você pode usar este recurso de uma linha

find . -maxdepth 1 -type d -print0 | xargs -0 -I {} sh -c 'echo -e $(find {} | wc -l) {}' | sort -n

Isso funcionará no sabor GNU e apenas omitirá o comando -e do comando echo para o BSD linux (por exemplo, OSX).


2
Excelente solução! O único problema que encontrei foram diretórios com espaços ou caracteres especiais. Adicione aspas onde o nome do dir é usado:find . -maxdepth 1 -type d -print0 | xargs -0 -I {} sh -c 'echo -e $(find "{}" | wc -l) "{}"' | sort -n
John Kary

1
Eu o modifiquei um pouco e funciona muito bem para mim:find . -maxdepth 1 -type d -print0 | xargs -0 -I {} sh -c 'echo $(find {} | wc -l) \\t {}' | sort -rn | less
Wizek

Meus comentários sobre a resposta de @ Sebastian também se aplicam aqui. O uso de echo -e(ou apenas `echo` como no comentário anterior) em um nome de diretório não citado troca um problema por outro.
tripleee

8

Se você deseja evitar casos de erro, não permita wc -lver arquivos com novas linhas (que contarão com mais de 2 arquivos)

por exemplo, considere um caso em que tenhamos um único arquivo com um único caractere EOL

> mkdir emptydir && cd emptydir
> touch $'file with EOL(\n) character in it'
> find -type f
./file with EOL(?) character in it
> find -type f | wc -l
2

Como pelo menos o gnu wcparece não ter a opção de ler / contar uma lista terminada nula (exceto de um arquivo), a solução mais fácil seria não passar os nomes dos arquivos, mas uma saída estática sempre que um arquivo for encontrado, por exemplo no mesmo diretório acima

> find -type f -exec printf '\n' \; | wc -l
1

Ou se o seu findsuportar

> find -type f -printf '\n' | wc -l
1 

7

Você pode usar o comando ncdu. Contará recursivamente quantos arquivos um diretório Linux contém. Aqui está um exemplo de saída:

insira a descrição da imagem aqui

Possui uma barra de progresso, o que é conveniente se você tiver muitos arquivos:

insira a descrição da imagem aqui

Para instalá-lo no Ubuntu:

sudo apt-get install -y ncdu

Referência: usei https://archive.org/details/cv_corpus_v1.tar (380390 arquivos, 11 GB) como a pasta em que é preciso contar o número de arquivos.

  • find . -type f | wc -l: cerca de 1m20s para concluir
  • ncdu: cerca de 1m20s para concluir

Isso calcula principalmente o uso do disco, não o número de arquivos. Essa sobrecarga adicional provavelmente não é desejada. (além da necessidade de instalar um pacote adicional para algo que pode ser feito com utilitários POSIX padrão)
hek2mgl

@ hek2mgl Ele calcula o número de arquivos, como mostrado em vermelho na primeira captura de tela. Demorei alguns minutos para ~ 2 milhões de arquivos, então a velocidade não é muito ruim.
Franck Dernoncourt

2
@ hek2mgl Adicionei uma referência reproduzível na resposta, executei-a duas vezes e não vi nenhuma diferença entre find . -type f | wc -le ncdu.
Franck Dernoncourt

2
sim, parece que findestá executando o processo mais ou menos o mesmo sistema que o duqual é o back-end ncdu. Apenas os tracei.
precisa saber é o seguinte

1
@FranckDernoncourt adorou. Eu tenho vários arquivos em uma pasta e ter uma barra de progresso salva a vida. Obrigado por compartilhar!
22718 Geek


4

Para determinar quantos arquivos existem no diretório atual, insira ls -1 | wc -l. Isso costuma wcfazer uma contagem do número de linhas (-l)na saída de ls -1. Não conta dotfiles. Observe que ls -l(que é um "L" em vez de um "1", como nos exemplos anteriores), que eu usei nas versões anteriores deste HOWTO, fornecerá uma contagem de arquivos maior que a contagem real. Obrigado a Kam Nejad por esse ponto.

Se você deseja contar apenas arquivos e NÃO incluir links simbólicos (apenas um exemplo do que mais você poderia fazer), use-o ls -l | grep -v ^l | wc -l(desta vez, é um "L" e não um "1", queremos uma lista "longa" aqui) . grepverifica qualquer linha que comece com "l" (indicando um link) e descarta essa linha (-v).

Velocidade relativa: "ls -1 / usr / bin / | wc -l" leva cerca de 1,03 segundos em um 486SX25 descarregado (/ usr / bin / nesta máquina possui 355 arquivos). " ls -l /usr/bin/ | grep -v ^l | wc -l" leva cerca de 1,19 segundos.

Fonte: http://www.tldp.org/HOWTO/Bash-Prompt-HOWTO/x700.html


2
ls -ldeve fazer statsyscall em cada arquivo para ler seu tamanho, mtime e outras propriedades, o que é lento. Em grandes diretórios (mais de 100.000 arquivos), a execução ls -lpode levar vários minutos. Portanto, para contar apenas arquivos, sempre use ls -1 | wc -l.
Marki555

A486SX25, nice
cam8001 5/17

ls -1ainda pode ser lento em diretórios grandes, porque precisa classificar os arquivos. Simplesmente printf '%s\n' *faz a mesma coisa e evita a lschamada externa (que é problemática de qualquer maneira), mas a solução mais eficiente é usar um comando que não realiza nenhuma classificação, como find. (A saída glob é classificada pelo shell.) #
Triplee

4

Se você precisar contar recursivamente um tipo de arquivo específico , poderá:

find YOUR_PATH -name '*.html' -type f | wc -l 

-l é apenas para exibir o número de linhas na saída.


A extensão é parte do nome do arquivo e não pode representar o tipo de arquivo
Waxhead

4

Com bash:

Crie uma matriz de entradas com () e obtenha a contagem com #.

FILES=(./*); echo ${#FILES[@]}

Ok, isso não conta recursivamente os arquivos, mas eu queria mostrar a opção simples primeiro. Um caso de uso comum pode ser para criar backups de substituição de um arquivo. Isso criará logfile.1, logfile.2, logfile.3 etc.

CNT=(./logfile*); mv logfile logfile.${#CNT[@]}

Contagem recursiva com o bash 4+ globstarativado (como mencionado por @tripleee)

FILES=(**/*); echo ${#FILES[@]}

Para obter a contagem de arquivos recursivamente, ainda podemos usar o find da mesma maneira.

FILES=(`find . -type f`); echo ${#FILES[@]}

Os shells modernos oferecem suporte **/*para enumeração recursiva. Ainda é menos eficiente do que findem diretórios grandes, porque o shell precisa classificar os arquivos em cada diretório.
tripleee

2

Para diretórios com espaços no nome ... (com base nas várias respostas acima) - imprima recursivamente o nome do diretório com o número de arquivos dentro de:

find . -mindepth 1 -type d -print0 | while IFS= read -r -d '' i ; do echo -n $i": " ; ls -p "$i" | grep -v / | wc -l ; done

Exemplo (formatado para facilitar a leitura):

pwd
  /mnt/Vancouver/Programming/scripts/claws/corpus

ls -l
  total 8
  drwxr-xr-x 2 victoria victoria 4096 Mar 28 15:02 'Catabolism - Autophagy; Phagosomes; Mitophagy'
  drwxr-xr-x 3 victoria victoria 4096 Mar 29 16:04 'Catabolism - Lysosomes'

ls 'Catabolism - Autophagy; Phagosomes; Mitophagy'/ | wc -l
  138

## 2 dir (one with 28 files; other with 1 file):
ls 'Catabolism - Lysosomes'/ | wc -l
  29

A estrutura de diretórios é melhor visualizada usando tree:

tree -L 3 -F .
  .
  ├── Catabolism - Autophagy; Phagosomes; Mitophagy/
  │   ├── 1
  │   ├── 10
  │   ├── [ ... SNIP! (138 files, total) ... ]
  │   ├── 98
  │   └── 99
  └── Catabolism - Lysosomes/
      ├── 1
      ├── 10
      ├── [ ... SNIP! (28 files, total) ... ]
      ├── 8
      ├── 9
      └── aaa/
          └── bbb

  3 directories, 167 files

man find | grep mindep
  -mindepth levels
    Do not apply any tests or actions at levels less than levels
    (a non-negative integer).  -mindepth 1 means process all files
    except the starting-points.

ls -p | grep -v /(usado abaixo) é da resposta 2 em /unix/48492/list-only-regular-files-but-not-directories-in-current-directory

find . -mindepth 1 -type d -print0 | while IFS= read -r -d '' i ; do echo -n $i": " ; ls -p "$i" | grep -v / | wc -l ; done
./Catabolism - Autophagy; Phagosomes; Mitophagy: 138
./Catabolism - Lysosomes: 28
./Catabolism - Lysosomes/aaa: 1

Applcation: Quero encontrar o número máximo de arquivos entre várias centenas de diretórios (toda a profundidade = 1) [saída abaixo novamente formatada para facilitar a leitura]:

date; pwd
    Fri Mar 29 20:08:08 PDT 2019
    /home/victoria/Mail/2_RESEARCH - NEWS

time find . -mindepth 1 -type d -print0 | while IFS= read -r -d '' i ; do echo -n $i": " ; ls -p "$i" | grep -v / | wc -l ; done > ../../aaa
    0:00.03

[victoria@victoria 2_RESEARCH - NEWS]$ head -n5 ../../aaa
    ./RNA - Exosomes: 26
    ./Cellular Signaling - Receptors: 213
    ./Catabolism - Autophagy; Phagosomes; Mitophagy: 138
    ./Stress - Physiological, Cellular - General: 261
    ./Ancient DNA; Ancient Protein: 34

[victoria@victoria 2_RESEARCH - NEWS]$ sed -r 's/(^.*): ([0-9]{1,8}$)/\2: \1/g' ../../aaa | sort -V | (head; echo ''; tail)

    0: ./Genomics - Gene Drive
    1: ./Causality; Causal Relationships
    1: ./Cloning
    1: ./GenMAPP 2
    1: ./Pathway Interaction Database
    1: ./Wasps
    2: ./Cellular Signaling - Ras-MAPK Pathway
    2: ./Cell Death - Ferroptosis
    2: ./Diet - Apples
    2: ./Environment - Waste Management

    988: ./Genomics - PPM (Personalized & Precision Medicine)
    1113: ./Microbes - Pathogens, Parasites
    1418: ./Health - Female
    1420: ./Immunity, Inflammation - General
    1522: ./Science, Research - Miscellaneous
    1797: ./Genomics
    1910: ./Neuroscience, Neurobiology
    2740: ./Genomics - Functional
    3943: ./Cancer
    4375: ./Health - Disease 

sort -Vé um tipo natural. ... Então, meu número máximo de arquivos em qualquer um desses diretórios (Claws Mail) é 4375 arquivos. Se eu deixei o teclado esquerdo ( https://stackoverflow.com/a/55409116/1904943 ) esses nomes de arquivos - todos são nomeados numericamente, começando com 1, em cada diretório - e preencho até 5 dígitos no total, eu deveria estar bem .


Termo aditivo

Encontre o número total de arquivos, subdiretórios em um diretório.

$ date; pwd
Tue 14 May 2019 04:08:31 PM PDT
/home/victoria/Mail/2_RESEARCH - NEWS

$ ls | head; echo; ls | tail
Acoustics
Ageing
Ageing - Calorie (Dietary) Restriction
Ageing - Senescence
Agriculture, Aquaculture, Fisheries
Ancient DNA; Ancient Protein
Anthropology, Archaeology
Ants
Archaeology
ARO-Relevant Literature, News

Transcriptome - CAGE
Transcriptome - FISSEQ
Transcriptome - RNA-seq
Translational Science, Medicine
Transposons
USACEHR-Relevant Literature
Vaccines
Vision, Eyes, Sight
Wasps
Women in Science, Medicine

$ find . -type f | wc -l
70214    ## files

$ find . -type d | wc -l
417      ## subdirectories

1

Eu escrevi ffcnt para acelerar a contagem recursiva de arquivos sob circunstâncias específicas: discos rotacionais e sistemas de arquivos que suportam o mapeamento de extensão.

Pode ser uma ordem de magnitude mais rápida do que lsou com findbase em abordagens, mas YMMV.


0

Há muitas respostas corretas aqui. Aqui está outro!

find . -type f | sort | uniq -w 10 -c

onde .está a pasta para procurar e 10é o número de caracteres pelos quais agrupar o diretório.


-1

encontre o tipo f | wc -l

OU (se o diretório for o diretório atual)

encontrar . tipo f | wc -l


Isso duplica pelo menos uma outra resposta para essa mesma pergunta.
Kusalananda

-1

Isso funcionará completamente bem. Curto simples. Se você deseja contar o número de arquivos presentes em uma pasta.

ls | wc -l

3
Primeiro de tudo, isso não responde à pergunta. A questão é sobre a contagem recursiva de arquivos de um diretório para a frente e o comando que você mostra não faz isso. além disso, com ls você está contando diretórios e arquivos. Além disso, não há motivo para responder a uma pergunta antiga se você não deseja adicionar algo novo e nem mesmo lê a pergunta corretamente. Evite fazê-lo.
XFCC 10/04

-1

Essa abordagem alternativa com a filtragem de formato conta todos os módulos disponíveis do grub kernel:

ls -l /boot/grub/*.mod | wc -l

-3
ls -l | grep -e -x -e -dr | wc -l 
  1. Lista longa
  2. filtrar arquivos e diretórios
  3. conte a linha filtrada não
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.