Como conto todos os arquivos recursivamente através de diretórios

47

Quero ver quantos arquivos existem nos subdiretórios para descobrir onde todo o uso do inode está no sistema. Mais ou menos como eu faria isso pelo uso do espaço

du -sh /*

o que me dará o espaço usado nos diretórios fora da raiz, mas nesse caso eu quero o número de arquivos, não o tamanho.

xenoterracida
fonte
Eu acho que "quantos arquivos existem em subdiretórios nos subdiretórios" é uma construção confusa. Se indicar com mais clareza o que você deseja, poderá obter uma resposta que se encaixe na conta.
Steven D
@ Steven, sinta-se à vontade para reescrevê-lo ... Pensei que meu exemplo du -sh /*deixou bem claro como eu queria que a contagem funcionasse. mesma coisa, basta contar os arquivos e não os bytes.
Xenoterracide
Como você mencionou o uso do inode, não entendo se você deseja contar o número de arquivos ou o número de inodes usados. Os dois são diferentes quando há links físicos no sistema de arquivos. A maioria das respostas, se não todas, fornece o número de arquivos. Não os use em um disco de backup do Apple Time Machine.
Mouviciel
@mouviciel isso não está sendo usado em um disco de backup, e sim, suponho que possam ser diferentes, mas no ambiente em que estou existem muito poucos hardlinks, tecnicamente, só preciso ter uma idéia disso. descobrir onde alguém está queimando lá fora cota de inode.
Xenoterracide

Respostas:

60
find -maxdepth 1 -type d | while read -r dir; do printf "%s:\t" "$dir"; find "$dir" -type f | wc -l; done

Agradecimentos a Gilles e xenoterracide pelas correções de segurança / compatibilidade.

A primeira parte: find -maxdepth 1 -type dretornará uma lista de todos os diretórios no diretório de trabalho atual. Isso é canalizado para ...

A segunda parte: while read -r dir; doinicia um loop while - enquanto o canal entrando no while estiver aberto (que é até que toda a lista de diretórios seja enviada), o comando read colocará a próxima linha na variável "dir". Então continua ...

A terceira parte: printf "%s:\t" "$dir";imprimirá a string em "$ dir" (que contém um dos nomes de diretório) seguido por uma guia.

A quarta parte: find "$dir -f file"faz uma lista de todos os arquivos dentro do nome do diretório contido em "$ dir". Esta lista é enviada para ..

A quinta parte: wc -l;conta o número de linhas que são enviadas para sua entrada padrão.

A parte final: donesimplesmente termina o loop while.

Portanto, obtemos uma lista de todos os diretórios no diretório atual. Para cada um desses diretórios, geramos uma lista de todos os arquivos nele, para que possamos contar todos eles usando wc -l. O resultado será semelhante a:

./dir1: 234
./dir2: 11
./dir3: 2199
...
Shawn J. Goff
fonte
Sempre use read -rcomo readtrata simples barras invertidas especialmente. Então echo -en "$dir:\t", novamente, fará as barras invertidas; uma correção simples é usar em seu printf '%s:\t' "$dir"lugar. Em seguida, $dirdeve ser "$dir"( sempre use aspas duplas em torno das substituições de variáveis ).
Gilles 'SO- stop be evil'
modificado por sugestões do @Gilesfind -maxdepth 1 -type d | while read -r dir; do printf "%s:\t" "$dir"; find "$dir" | wc -l; done
xenoterracide
2
Eu estou adicionando sort -n -r -k2ao final deste, para os lotes de diretórios, de modo que eu sei onde o mais uso é
xenoterracide
A quarta parte: find "$ dir" faz uma lista de todos os arquivos dentro do nome do diretório contidos em "$ dir". Você esqueceu de adicionar -type fpara listar os arquivos:find -maxdepth 1 -type d | while read -r dir; do printf "%s:\t" "$dir"; find "$dir" -type f | wc -l; done
Krzysztof Boduch
@ krzysiek-boduch Obrigado! Eu atualizei a resposta.
Shawn J. Goff
15

Tente find . -type f | wc -l, ele contará todos os arquivos no diretório atual, bem como todos os arquivos nos subdiretórios. Observe que todos os diretórios não serão contados como arquivos, apenas arquivos comuns.

herohuyongtao
fonte
13

Aqui está uma compilação de alguns comandos úteis de listagem (redimensionados com base no código de usuários anteriores):

Listar pastas com contagem de arquivos:

find -maxdepth 1 -type d | sort | while read -r dir; do n=$(find "$dir" -type f | wc -l); printf "%4d : %s\n" $n "$dir"; done

Listar pastas com contagem de arquivos diferente de zero:

find -maxdepth 1 -type d | sort | while read -r dir; do n=$(find "$dir" -type f | wc -l); if [ $n -gt 0 ]; then printf "%4d : %s\n" $n "$dir"; fi; done

Listar pastas com contagem de subpastas:

find -maxdepth 1 -type d | sort | while read -r dir; do n=$(find "$dir" -type d | wc -l); let n--; printf "%4d : %s\n" $n "$dir"; done

Listar pastas com contagem de subpastas diferente de zero:

find -maxdepth 1 -type d | sort | while read -r dir; do n=$(find "$dir" -type d | wc -l); let n--; if [ $n -gt 0 ]; then printf "%4d : %s\n" $n "$dir"; fi; done

Listar pastas vazias:

find -maxdepth 1 -type d | sort | while read -r dir; do n=$(find "$dir" | wc -l); let n--; if [ $n -eq 0 ]; then printf "%4d : %s\n" $n "$dir"; fi; done

Listar pastas não vazias com contagem de conteúdo:

find -maxdepth 1 -type d | sort | while read -r dir; do n=$(find "$dir" | wc -l); let n--; if [ $n -gt 0 ]; then printf "%4d : %s\n" $n "$dir"; fi; done
DolphinDream
fonte
E, se você quiser que a saída de qualquer um desses comandos de lista seja classificada pela contagem de itens, envie o comando para uma classificação: "a-list-command" | sort -n
DolphinDream
12

Experimentar:

find /path/to/start/at -type f -print | wc -l

como ponto de partida ou se você realmente deseja apenas recursar pelos subdiretórios de um diretório (e pular os arquivos nesse diretório de nível superior)

find `find /path/to/start/at -mindepth 1 -maxdepth 1 -type d -print` -type f -print | wc -l
Cry Havok
fonte
+1 para alguma coisa | wc -l ... contagem de palavras é como uma ferramenta agradável pouco
Johan
Sim, mas isso só contém 1 diretório .... Gostaria de obter a contagem de todos os diretórios em um diretório e não quero executá-lo separadamente a cada vez ... é claro, acho que poderia usar um loop ... mas estou sendo preguiçoso.
Xenoterracide
findfunciona recursivamente por todos os subdiretórios por padrão. Se você deseja que ele funcione em vários locais, é possível especificar todos eles entre finde -type.
Didier Trosset
esse segundo certamente não funciona ... Eu tentei em / em casa. Eu tenho 698035 . Eu deveria ver cerca de 6 números.
Xenoterracide
Funciona para mim - você tem certeza de que possui apenas 6 arquivos /home? Eu estaria 100% certo de que você não.
Cry Havok
4

A solução a seguir conta o número real de inodes usados ​​a partir do diretório atual:

find . -print0 | xargs -0 -n 1 ls -id | cut -d' ' -f1 | sort -u | wc -l

Para obter o número de arquivos do mesmo subconjunto, use:

find . | wc -l

Para soluções que exploram apenas subdiretórios, sem levar em conta os arquivos no diretório atual, você pode consultar outras respostas.

mouviciel
fonte
1
Boa ideia, levando em consideração os links físicos. Assumindo GNU achado, você não precisa de tantos passos: find -printf '%i\n' | sort -u | wc -l. Se você queria ser portátil, seria necessário find . -exec ls -id {} + | cut ….
Gilles 'SO- stop be evil'
2

O OS X 10.6 engasga com o comando na resposta aceita, porque não especifica um caminho para find. Em vez disso, use:

find . -maxdepth 1 -type d | while read -r dir; do printf "%s:\t" "$dir"; find "$dir" -type f | wc -l; done
abeboparebop
fonte
2

Sei que estou atrasado para a festa, mas acredito que essa bashsolução pura (ou outra concha que aceite globos de estrela dupla) possa ser muito mais rápida em algumas situações:

shopt -s globstar    # to enable ** glob in bash
for dir in */; do a=( "$dir"/**/* ); printf "%s\t%s\n" "$dir:" "${#a[*]}"; done

resultado:

d1/:    302
d2/:    24
d3/:    640
...
jimmij
fonte
1

Faça uma tentativa:

find -type d -print0 | xargs -0 -I {} sh -c 'printf "%s\t%s\n" "$(find "{}" -maxdepth 1 -type f | wc -l)" "{}"'

Deve funcionar bem, a menos que os nomes de arquivos incluam novas linhas.

Dennis Williamson
fonte
muito recursivo ... Eu só quero ver o nível superior, onde totaliza tudo abaixo dele. totalizado ... isso acaba imprimindo todos os diretórios.
Xenoterracide
@xenoterracide: tente adicionar -maxdepth 1imediatamente após o primeiro find. Se você deseja incluir o número de subdiretórios em sua contagem, remova o -type fno final (isso deveria ter sido realmente ! -type dassim mesmo, para que todos os arquivos que não sejam de diretório fossem incluídos).
Dennis Williamson
1

Se você tiver o ncduinstalado (obrigatório quando você quiser fazer uma limpeza), digite c"Alternar a exibição das contagens de itens filhos". E Cpara "Classificar por itens".

Demi-Lune
fonte
1
lol, esta deve ser a resposta mais aceita
x-yuri
0

du --inodes

Não sei por que ninguém (inclusive eu) estava ciente de:

du --inodes
--inodes
      list inode usage information instead of block usage

Tenho certeza de que isso resolve o problema do OP. Comecei a usá-lo muito para descobrir onde está todo o lixo em minhas unidades enormes (e descarregá-lo em um disco antigo).

Mais informações

Se você NÃO deseja recorrer (o que pode ser útil em outras situações), adicione

-S, --separate-dirs
Sridhar Sarnobat
fonte