Qual é a melhor maneira de contar o número de arquivos em um diretório?

10

Se a análise da saída de ls for perigosa porque pode quebrar alguns caracteres funky (espaços, \n , ...), qual é a melhor maneira de saber o número de arquivos em um diretório?

Eu costumo confiar em find para evitar essa análise, mas da mesma forma, find mydir | wc -l vai quebrar pelas mesmas razões.

Estou trabalhando no Solaris agora, mas estou procurando uma resposta tão portátil quanto possível em diferentes uniões e diferentes shells.

    
por rahmu 23.12.2011 / 11:39

10 respostas

14

Que tal esse truque?

find . -maxdepth 1 -exec echo \; | wc -l

Tão portável quanto find e wc .

    
por 23.12.2011 / 13:03
11

Com bash, sem utilitários externos, nem loops:

shopt -s dotglob
files=(*)
echo ${#files[@]}

Em ksh, substitua shopt -s dotglob por FIGNORE=.?(.) . Em zsh, substitua-o por setopt glob_dots ou remova a chamada shopt e use files=(*(D)) . (Ou simplesmente solte a linha se você não quiser incluir arquivos de ponto.) Portably, se você não se importa com arquivos de ponto:

set -- *
echo $#

Se você quiser incluir arquivos de ponto:

set -- *
if [ -e "$1" ]; then c=$#; else c=0; fi
set .[!.]*
if [ -e "$1" ]; then c=$((c+$#)); fi
set ..?*
if [ -e "$1" ]; then c=$((c+$#)); fi
echo $c
    
por 23.12.2011 / 19:02
6

Tente:

ls -b1A | wc -l

O -b terá caracteres não imprimíveis, -A mostrará todos os arquivos, exceto . e .. e um por linha (o padrão em um canal, mas bom ser explícito).

Contanto que incluamos linguagens de script de nível mais alto, aqui está uma de uma linha em Python:

python -c 'import os; print len(os.listdir(os.sep))'

Ou com 'encontrar' completo:

python -c 'import os; print len([j for i in os.walk(os.sep) for j in i[1]+i[2]])'
    
por 23.12.2011 / 16:33
6
find . ! -name . -prune -print | grep -c /

Deve ser razoavelmente portátil para sistemas pós-80s.

Isso conta todas as entradas do diretório, exceto . e .. no diretório atual.

Para contar arquivos em subdiretórios também:

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

(aquele deve ser portátil até mesmo para Unix V6 (1975), já que não precisa de -prune )

    
por 09.05.2015 / 15:28
1

O Yoc pode usar essa construção:

I=0; for i in * ; do ((I++)); done ; echo $I

Mas eu tenho medo, você pode causar erro como Argument list too long. no caso de ter muitos arquivos no diretório. No entanto eu testei no diretório com 10 bilhões de arquivos, e funcionou bem.

    
por 23.12.2011 / 11:51
1

Já considerou o perl, que deve ser relativamente portátil?

Algo como:

use File::Find;

$counter = 0;

sub wanted { 
  -f && ++$counter
}

find(\&wanted, @directories_to_search);
print "$counter\n";
    
por 23.12.2011 / 15:39
0

Tente isto = > Usando ls com -i (para o número do nó) & -F (acrescenta o nome do diretório com '/') opções.

ls -ilF | egrep -v '/' | wc -l
    
por 24.12.2011 / 11:21
0

Com perl one-liner (reformatado para legibilidade):

perl -e 'opendir($dh, ".");
         while ( readdir($dh) ) {$count++};
         closedir $dh;
         print "$count\n";'

ou

perl -e 'opendir($dh, ".");
         @files = readdir($dh);
         closedir $dh;
         print $#files+1,"\n";'

Você pode usar as funções perl que modificam matrizes como grep ou map com a segunda versão. Veja perldoc -f readdir para um exemplo usando grep .

    
por 11.06.2016 / 06:30
0

A versão mais simples que uso o tempo todo e nunca tive problemas é: ls -b1 | wc -l

    
por 08.08.2017 / 15:00
0

Além da resposta find -based proposta por Stéphane , aqui está uma resposta compatível com POSIX com base em ls :

ls -qf | tail -n +3 | wc -l
    
por 15.08.2017 / 20:36