Que tal esse truque?
find . -maxdepth 1 -exec echo \; | wc -l
Tão portável quanto find
e wc
.
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.
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
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]])'
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
)
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.
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";
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
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
.
A versão mais simples que uso o tempo todo e nunca tive problemas é:
ls -b1 | wc -l
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