Respostas:
Tente isto em vez (require find
's -printf
suporte):
find <expr> -type f -printf '.' | wc -c
Será mais confiável e rápido do que contar as linhas.
Observe que eu uso o find
's printf
, não um comando externo.
Vamos sentar um pouco:
$ ls -1
a
e
l
ll.sh
r
t
y
z
Meu snippet de referência:
$ time find -type f -printf '.' | wc -c
8
real 0m0.004s
user 0m0.000s
sys 0m0.007s
Com linhas completas:
$ time find -type f | wc -l
8
real 0m0.006s
user 0m0.003s
sys 0m0.000s
Então minha solução é mais rápida =) (a parte importante é a real
linha)
-printf '.'
Por que não
find <expr> | wc -l
como uma solução portátil simples? Sua solução original é gerar um novo processo printf
para cada arquivo individual encontrado, e isso é muito caro (como você acabou de descobrir).
Observe que isso será superestimado se você tiver nomes de arquivo com novas linhas incorporadas, mas se você tiver isso, suspeito que seus problemas sejam um pouco mais profundos.
Esta solução é certamente mais lenta do que algumas das outras find -> wc
soluções aqui, mas se você estivesse inclinado a fazer outra coisa com os nomes dos arquivos além de contá-los, você poderia a read
partir da find
saída.
n=0
while read -r -d ''; do
((n++)) # count
# maybe perform another act on file
done < <(find <expr> -print0)
echo $n
É apenas uma modificação de uma solução encontrada no BashGuide que lida adequadamente com arquivos com nomes fora do padrão, tornando o find
delimitador de saída um byte NUL usando print0
e lendo a partir dele usando ''
(byte NUL) como o delimitador de loop.
Esta é minha countfiles
função no meu ~/.bashrc
(é razoavelmente rápida, deve funcionar para Linux e FreeBSD find
e não se deixa enganar por caminhos de arquivo contendo caracteres de nova linha; o final wc
apenas conta bytes NUL):
countfiles ()
{
command find "${1:-.}" -type f -name "${2:-*}" -print0 |
command tr -dc '\0' | command wc -c;
return 0
}
countfiles
countfiles ~ '*.txt'