Como posso obter uma contagem de arquivos em um diretório usando a linha de comando?

193

Eu tenho um diretório com um grande número de arquivos. Não vejo uma lsopção para fornecer a contagem. Existe alguma mágica na linha de comando para obter uma contagem de arquivos?

Blake
fonte
tree . | tailou tree -a . | tailincluir arquivos / diretórios ocultos, treeé recursivo se é isso que você deseja.
CodyChan #

Respostas:

239

Usando uma ampla definição de "arquivo"

ls | wc -l

(observe que ele não conta os arquivos ocultos e assume que os nomes dos arquivos não contêm caracteres de nova linha).

Para incluir arquivos ocultos (exceto .e ..) e evitar problemas com caracteres de nova linha, a maneira canônica é:

find . ! -name . -prune -print | grep -c /

Ou recursivamente:

find .//. ! -name . -print | grep -c //
James Roth
fonte
23
wcé um programa de "contagem de palavras". A -lopção faz com que conte linhas. Nesse caso, está contando as linhas na saída de ls. Esta é sempre a maneira como me ensinaram a obter uma contagem de arquivos para um determinado diretório também.
Sandy
20
adicione nota que lssim ls -1se a saída for um tubo.
Lesmana
6
que não contém tudo em um diretório - você perdeu arquivos de pontos e também coleciona algumas linhas extras. Um diretório vazio ainda retornará 1 linha. E se você ligar ls -la, receberá três linhas no diretório. Você deseja ls -lA | wc -lpular as entradas .e ... Você ainda estará fora de um, no entanto.
1
Um diretório vazio retorna 0 para mim
James Roth
2
Uma abordagem corrigida, que não duplicaria a contagem de arquivos com novas linhas no nome, seria a seguinte: ls -q | wc -l- embora observe que os arquivos ocultos ainda não serão contados por essa abordagem e que os diretórios serão contados.
godlygeek
31

Para definição restrita de arquivo:

 find . -maxdepth 1 -type f | wc -l
Maciej Piechotka
fonte
E é claro que você pode omitir a -maxdepth 1contagem recursiva dos arquivos (ou ajustá-lo para a profundidade máxima de pesquisa desejada).
user7089
1
Se você tiver um arquivo cujo nome contenha uma nova linha, essa abordagem contará incorretamente duas vezes.
godlygeek
7
Uma abordagem corrigido, que não os arquivos de contagem duplos com novas linhas no nome, seria esta:find -maxdepth 1 -type f -printf "\n" | wc -l
godlygeek
+1 Permitir para arquivos ocultos e ignora diretórios
Michael Durrant
14
ls -1 | wc -l

...

$ ls --help | grep -- '  -1'
    -1                         list one file per line

...

$ wc --help | grep -- '  -l'
    -l, --lines            print the newline counts

PS: Nota ls - <número> | wc - <letter-l>

nicomen
fonte
10
A maioria das versões do lsfaz -1automaticamente quando a saída é para um tubo.
Dennis Williamson
3
@ Dennis isso é interessante, eu não sabia que um aplicativo poderia dizer que sua saída estava indo para um cano.
Xenoterracide
1
Editei esta versão por ser mais explícita. No entanto, sim ls usa -1 se for canalizado (tente: ls | cat), acho a sintaxe -1 mais explícita.
Gabe.
3
@xenoterracide: In Bash:[[ -p /dev/stdin ]] && echo "stdin is from a pipe"
Dennis Williamson
2
Nos meus testes, foi significativamente mais rápido também fornecer a opção -f para evitar a classificação dos nomes dos arquivos. Infelizmente, você ainda recebe a resposta errada se seus nomes de arquivos contiverem novas linhas.
Samuel Edwin Ward
10

Provavelmente a resposta mais completa usando ls/ wcpar é

ls -Aq | wc -l

se você deseja contar arquivos de ponto e

ls -q | wc -l

de outra forma.

  • -Aé contar arquivos de ponto, mas omita .e ...
  • -qfaça lssubstituir caracteres não gráficos, especificamente caracteres de nova linha, com ?, produzindo 1 linha para cada arquivo

Para obter uma saída de linha única lsno terminal (ou seja, sem conectá-la wc), a -1opção deve ser adicionada.

(comportamento de lstestado com coreutils 8.23)

Frax
fonte
2
Como você disse, -1não é necessário. Quanto a "ele lida com novas linhas nos nomes de arquivos de maneira sensata com a saída do console" , isso ocorre por causa da -qopção (que você deve usar em vez de -bser portátil) que "Força" cada instância de caracteres de nome de arquivo não imprimível e caracteres <tab> a serem gravados como o caractere <question-mark> ('?'). As implementações podem fornecer essa opção por padrão se a saída for para um dispositivo terminal. " Assim, por exemplo, ls -Aq | wc -lpara contar todos os arquivos / diretórios ou ls -qp | grep -c /para contar dirs único não-escondidos etc ...
don_crissti
Obrigado pela sua contribuição. Alterado -bpara -q.
Frax
7

Se você souber que o diretório atual contém pelo menos um arquivo não oculto:

set -- *; echo "$#"

Isso é obviamente generalizável para qualquer glob.

Em um script, isso tem o efeito colateral às vezes infeliz de substituir os parâmetros posicionais. Você pode contornar isso usando um subshell ou com uma função (versão Bourne / POSIX) como:

count_words () {
  eval 'shift; '"$1"'=$#'
}
count_words number_of_files *
echo "There are $number_of_files non-dot files in the current directory"

Uma solução alternativa é $(ls -d -- * | wc -l). Se a glob estiver *, o comando pode ser abreviado para $(ls | wc -l). Analisar a saída de lssempre me deixa desconfortável, mas aqui deve funcionar, desde que os nomes dos seus arquivos não contenham novas linhas ou que você os lsescape. E $(ls -d -- * 2>/dev/null | wc -l)tem a vantagem de lidar com o caso de um globo sem correspondência normalmente (ou seja, ele retorna 0 nesse caso, enquanto o set *método exige testes minuciosos se o globo estiver vazio).

Se os nomes dos arquivos puderem conter caracteres de nova linha, uma alternativa é usar $(ls -d ./* | grep -c /).

Qualquer uma dessas soluções que dependem de passar a expansão de uma glob lspode falhar com um erro muito longo da lista de argumentos se houver muitos arquivos correspondentes.

Gilles
fonte
1
Deseja realmente criar 13.923 parâmetros posicionais? E você deve fazer sua variável local localou eliminá-la: eval $1=$#ou apenas usar echo $#e fazer number_of_files=$(count_words *).
Dennis Williamson
1
@ Dennis: parte do ponto era evitar bifurcação. Eu acho que isso não é uma preocupação do século XXI. Ok, admito que não me importo mais com shells não POSIX, portanto, eu poderia ter evitado a variável temporária.
Gilles
Por que você subtraiu um $#(você não fez isso antes da edição)?
Dennis Williamson
@ Dennis: Ainda estou evitando um fork (bem, isso faz diferença em máquinas com uma CPU lenta, como roteadores) e passando um nome de variável como $1. Então, o que eu quero contar é o número de parâmetros que não são o primeiro parâmetro. (Eu não posso usar shiftporque eu preciso para manter o nome da variável ao redor.) (Umm, agora se você tivesse perguntado sobre a primeira linha ...)
Gilles
@ Dennis: venha para pensar sobre isso, eu posso usar shiftse eu tempo certo.
Gilles
7

Eu achei du --inodesútil, mas não tenho certeza de qual versão durequer. Deve ser substancialmente mais rápido do que abordagens alternativas usando finde wc.

No Ubuntu 17.10, o seguinte funciona:

du --inodes      # all files and subdirectories
du --inodes -s   # summary
du --inodes -d 2 # depth 2 at most

Combine com | sort -nrpara classificar decrescente pelo número de inodes contendo.

krlmlr
fonte
5

Ao usar o par ls / wc, se estivermos adicionando -U, será muito mais rápido (não classifique).

ls -AqU | wc -l
Jbnair
fonte
1
-Ué específico do GNU.
Stéphane Chazelas
4

Após instalar o comando tree, basta digitar:

tree

Se você quiser arquivos ocultos também:

tree -a

Se você estiver usando o Debian / Mint / Ubuntu Linux, digite o seguinte comando para instalar o comando tree:

sudo apt-get install tree

A opção -L é usada para especificar o nível máximo de exibição da árvore de diretórios. O comando tree não conta apenas o número de arquivos, mas também o número de diretórios, considerando quantos níveis da árvore de diretórios você desejar.

lev
fonte
Quando digito árvore, recebo uma espécie de saída de árvore na tela do diretório em que estou, mas não consigo ver onde o número de arquivos é mostrado.
Charles Darwin
2
find -maxdepth 1 -type f -printf . | wc -c
  • -maxdepth 1tornará não recursivo, findé recursivo por padrão
  • -type f incluirá apenas arquivos
  • -printf .é um toque fofo. imprime um ponto para cada arquivo em vez do nome do arquivo, e agora é capaz de lidar com qualquer nome de arquivo e também salva dados; nós apenas temos que contar os pontos :)
  • | wc -c conta caracteres
aude
fonte
1

Sem tubo, sem cópia de seqüência, sem forquilha, apenas um forro simples

$ fcount() { local f i=0; for f in *; do let i++; done; echo $i; }; fcount
DaboD
fonte
1
Dá o valor 1 se não houver arquivos no diretório. Não conta arquivos, conta arquivos e diretórios.
21417 steve
1

Aqui está outra técnica ao longo da linha que Gilles postou :

word_count () { local c=("$@"); echo "${#c[@]}"; }
file_count=$(word_count *)

que cria uma matriz com 13.923 elementos (se houver quantos arquivos houver).

Dennis Williamson
fonte
Qual é o sentido dessa cmatriz? word_count() { echo "$#"; }seria o suficiente. O objetivo da solução @Gilles é armazenar a contagem em uma variável retornada para evitar a necessidade de usar a substituição de comandos (que envolve um garfo e tubo em shells que não sejam ksh93).
Stéphane Chazelas
1
find . -type f -maxdepth 1 |  wc -l 

Isso pode listar apenas os arquivos no diretório atual.

pappu
fonte
find . -type fencontrará arquivos no diretório atual e também, recursivamente, nos subdiretórios.
dhag
0

Tente isso, espero que esta resposta o ajude

echo $((`ls -l | wc -l` -1 ))
Tigre
fonte
0

Você pode verificar com:

ls -l | grep -v ^l | wc -l
AMIC MING
fonte
0

Melhorando algumas respostas dadas antes, mas desta vez explicitamente.

$ tree -L 1 | tail -n 1 | cut -d " " -f 3

Vale a pena notar o uso de alguns comandos amados como taile cut. Além disso, observe que a árvore não está disponível por padrão. O comando acima captura primeiro informações sobre o diretório no nível 1, obtém a última linha tail -n 1onde está nosso objetivo e termina com cuta terceira palavra.

Por exemplo, localizando em /:

/ $ tree -L 1
.
├── 1
├── bin -> usr/bin
├── boot
├── dev
├── etc
├── home
├── lib -> usr/lib
├── lib64 -> usr/lib64
├── lost+found
├── media
├── mnt
├── opt
├── proc
├── root
├── run
├── sbin -> usr/sbin
├── srv
├── sys
├── tmp
├── usr
└── var

20 directories, 1 file
/ $ tree -L 1 | tail -n 1
20 directories, 1 file
/ $ tree -L 1 | tail -n 1 | cut -d " " -f 3
1

Então, que tal perguntar o número de diretórios?

jonaprieto
fonte
0

No Linux, para tornar o comando muito robusto e manipular arquivos que possam ter novas linhas em seus nomes, use o seguinte:

find -maxdepth 1 -type f -print0 | tr -cd '\0' | wc -c

Isso nos salva da provação de analisar a lssaída.


Palavras-chave:

codeforester
fonte
-2

Use o treecomando, apenas:

tree
user115186
fonte