Resposta curta:
\ls -afq | wc -l
(Isso inclui .e .., portanto, subtraia 2.)
Quando você lista os arquivos em um diretório, três coisas comuns podem acontecer:
- Enumerando os nomes de arquivo no diretório Isso é inevitável: não há como contar os arquivos em um diretório sem enumerá-los.
- Classificando os nomes dos arquivos. Os curingas do shell e o
lscomando fazem isso.
- Chamando
statpara recuperar metadados sobre cada entrada de diretório, como se é um diretório.
O número 3 é o mais caro, de longe, porque requer o carregamento de um inode para cada arquivo. Em comparação, todos os nomes de arquivos necessários para o nº 1 são armazenados compactamente em alguns blocos. O nº 2 desperdiça algum tempo de CPU, mas geralmente não é um disjuntor.
Se não houver novas linhas nos nomes dos arquivos, um simples ls -A | wc -linforma quantos arquivos existem no diretório. Lembre-se de que, se você tiver um apelido para ls, isso pode acionar uma chamada para stat(por exemplo, ls --colorou ls -Fprecisar saber o tipo de arquivo, o qual requer uma chamada para stat); portanto, na linha de comando, ligue command ls -A | wc -lou \ls -A | wc -lpara evitar um apelido.
Se houver novas linhas no nome do arquivo, se as novas linhas estão listadas ou não, depende da variante Unix. O coreutils GNU e o BusyBox assumem o padrão de exibição ?para uma nova linha, para que sejam seguros.
Ligue ls -fpara listar as entradas sem classificá-las (nº 2). Isso é ativado automaticamente -a(pelo menos nos sistemas modernos). A -fopção está no POSIX, mas com status opcional; a maioria das implementações suporta, mas não o BusyBox. A opção -qsubstitui caracteres não imprimíveis, incluindo novas linhas por ?; é POSIX, mas não é suportado pelo BusyBox, portanto, omita-o se você precisar do suporte ao BusyBox às custas da contagem excessiva de arquivos cujo nome contém um caractere de nova linha.
Se o diretório não tiver subdiretórios, a maioria das versões findnão chamará statsuas entradas (otimização de diretório em folha: um diretório com uma contagem de links 2 não pode ter subdiretórios, portanto, findnão é necessário procurar os metadados das entradas, a menos que condição -typerequerida). Assim, find . | wc -lé uma maneira portátil e rápida de contar arquivos em um diretório, desde que o diretório não tenha subdiretórios e que nenhum nome de arquivo contenha uma nova linha.
Se o diretório não possuir subdiretórios, mas os nomes dos arquivos puderem conter novas linhas, tente um destes (o segundo deve ser mais rápido se for suportado, mas pode não ser notável).
find -print0 | tr -dc \\0 | wc -c
find -printf a | wc -c
Por outro lado, não use findse o diretório tiver subdiretórios: inclusive find . -maxdepth 1chama statcada entrada (pelo menos com o GNU find e BusyBox find). Você evita a classificação (nº 2), mas paga o preço de uma pesquisa de inode (nº 3) que reduz o desempenho.
No shell sem ferramentas externas, é possível executar a contagem dos arquivos no diretório atual com set -- *; echo $#. Isso perde arquivos de ponto (arquivos cujo nome começa com .) e informa 1 em vez de 0 em um diretório vazio. Essa é a maneira mais rápida de contar arquivos em diretórios pequenos, pois não requer o início de um programa externo, mas (exceto no zsh) perde tempo para diretórios maiores devido à etapa de classificação (# 2).
No bash, esta é uma maneira confiável de contar os arquivos no diretório atual:
shopt -s dotglob nullglob
a=(*)
echo ${#a[@]}
No ksh93, esta é uma maneira confiável de contar os arquivos no diretório atual:
FIGNORE='@(.|..)'
a=(~(N)*)
echo ${#a[@]}
No zsh, esta é uma maneira confiável de contar os arquivos no diretório atual:
a=(*(DNoN))
echo $#a
Se você tem o mark_dirsconjunto de opção, certifique-se de desligá-lo: a=(*(DNoN^M)).
Em qualquer shell POSIX, esta é uma maneira confiável de contar os arquivos no diretório atual:
total=0
set -- *
if [ $# -ne 1 ] || [ -e "$1" ] || [ -L "$1" ]; then total=$((total+$#)); fi
set -- .[!.]*
if [ $# -ne 1 ] || [ -e "$1" ] || [ -L "$1" ]; then total=$((total+$#)); fi
set -- ..?*
if [ $# -ne 1 ] || [ -e "$1" ] || [ -L "$1" ]; then total=$((total+$#)); fi
echo "$total"
Todos esses métodos classificam os nomes dos arquivos, exceto o zsh.
ls -l|wc -lseria desligado por uma devido ao total de blocos na primeira linha dels -lsaída