Qual é a melhor maneira de contar os resultados “encontrados”?
97
Minha solução atual seria find <expr> -exec printf '.' \; | wc -c, mas isso leva muito tempo quando há mais de 10.000 resultados. Não há maneira mais rápida / melhor de fazer isso?
Não é mais confiável se o sinalizador -printf para localizar não for compatível com sua plataforma. ;-)
Randy Howard
7
Observe que você pode economizar alguns nanossegundos a mais não citando o ponto-printf '.'
Jens
6
@Jens - especialmente quando você leva em consideração o tempo necessário para digitar isso
Brian Agnew
6
Com um benchmark tão pequeno, os tempos são provavelmente dominados por outros fatores além do que você deseja medir. Um experimento com uma grande árvore seria mais útil. Mas isso recebe meu voto para realmente fazer o que o OP pediu.
tripleee
132
Por que não
find <expr>| wc -l
como uma solução portátil simples? Sua solução original é gerar um novo processoprintf 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.
-1: irá quebrar no arquivo com novas linhas, e é mais lento do que contar bytes =)
Gilles Quenot
21
Eu não acho que justifique uma votação negativa, visto que a limitação de nome de arquivo / nova linha é muito rara e mencionada acima. Mais devagar ? Possivelmente. Dado que você está consultando um sistema de arquivos, suspeito que a diferença de velocidade seja pequena. Em todos os meus 10.000 arquivos, medi uma diferença de 3 ms
Brian Agnew,
8
A diferença de desempenho entre 'find <expr> | wc -l' e 'find <expr> -printf. | wc -c 'são extremamente pequenos. O armazenamento em cache (ou seja, se você executar o mesmo find duas vezes na mesma árvore) é muito mais importante. IMHO a solução com "wc -l" é muito mais intuitiva.
pitseeker
4
Esta solução é certamente mais lenta do que algumas das outras find -> wcsoluções aqui, mas se você estivesse inclinado a fazer outra coisa com os nomes dos arquivos além de contá-los, você poderia a readpartir da findsaída.
n=0while read -r -d '';do((n++))# count# maybe perform another act on filedone<<(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 finddelimitador de saída um byte NUL usando print0e lendo a partir dele usando ''(byte NUL) como o delimitador de loop.
Esta é minha countfilesfunção no meu ~/.bashrc(é razoavelmente rápida, deve funcionar para Linux e FreeBSD finde não se deixa enganar por caminhos de arquivo contendo caracteres de nova linha; o final wcapenas conta bytes NUL):
Respostas:
Tente isto em vez (require
find
's-printf
suporte):Será mais confiável e rápido do que contar as linhas.
Observe que eu uso o
find
'sprintf
, não um comando externo.Vamos sentar um pouco:
Meu snippet de referência:
Com linhas completas:
Então minha solução é mais rápida =) (a parte importante é a
real
linha)fonte
-printf '.'
Por que não
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.
fonte
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 aread
partir dafind
saída.É 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 usandoprint0
e lendo a partir dele usando''
(byte NUL) como o delimitador de loop.fonte
Esta é minha
countfiles
função no meu~/.bashrc
(é razoavelmente rápida, deve funcionar para Linux e FreeBSDfind
e não se deixa enganar por caminhos de arquivo contendo caracteres de nova linha; o finalwc
apenas conta bytes NUL):fonte