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.