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


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 //

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

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>


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)


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.


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.


5

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

ls -AqU | wc -l

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.


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

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

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).


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.


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 ))


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?



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.