Qual è il modo migliore per contare i risultati "trova"?


97

La mia soluzione attuale sarebbe find <expr> -exec printf '.' \; | wc -c, ma questo richiede troppo tempo quando ci sono più di 10000 risultati. Non esiste un modo migliore / più veloce per farlo?


usa wc -l sui risultati della ricerca
— Manuel Selva

Risposte:


82

Prova questo invece (richiede findil -printfsupporto di):

find <expr> -type f -printf '.' | wc -c

Sarà più affidabile e più veloce del conteggio delle linee.

Nota che uso find's printf, non un comando esterno.


Mettiamo un po 'in panchina:

$ ls -1
a
e
l
ll.sh
r
t
y
z

Il mio benchmark di snippet:

$ time find -type f -printf '.' | wc -c
8

real    0m0.004s
user    0m0.000s
sys     0m0.007s

Con righe complete:

$ time find -type f | wc -l
8

real    0m0.006s
user    0m0.003s
sys     0m0.000s

Quindi la mia soluzione è più veloce =) (la parte importante è la reallinea)


6
Non equivalente, è più affidabile =)
— Gilles Quenot

6
Non è più affidabile se il flag -printf da trovare non è supportato sulla tua piattaforma. ;-)
— Randy Howard

7
Nota che puoi raderti qualche nanosecondo in più non citando il punto in-printf '.'
— Jens

6
@Jens - soprattutto quando si prende in considerazione il tempo necessario per digitare che
— Brian Agnew

6
Con un benchmark così piccolo, i tempi sono probabilmente dominati da altri fattori oltre a ciò che si desidera misurare. Un esperimento con un grande albero sarebbe più utile. Ma questo ottiene il mio voto per aver effettivamente fatto ciò che l'OP ha chiesto.
— tripleee

132

Perchè no

find <expr> | wc -l

come una semplice soluzione portatile? La tua soluzione originale sta generando un nuovo processo printf per ogni singolo file trovato, ed è molto costoso (come hai appena trovato).

Nota che questo conterà in eccesso se hai nomi di file con newline incorporati, ma se lo hai, sospetto che i tuoi problemi siano un po 'più profondi.


9
-1: si interromperà il file con una nuova riga ed è più lento del conteggio dei byte =)
— Gilles Quenot

21
Non credo che ciò giustifichi un voto negativo dato che la limitazione del nome file / nuova riga è piuttosto rara e indicata sopra. Più lentamente ? Forse. Dato che stai interrogando un filesystem, sospetto che la differenza di velocità sia piccola. Nei miei 10.000 file misuro una differenza di 3 ms
— Brian Agnew

8
La differenza di prestazioni tra 'find <expr> | wc -l' e 'find <expr> -printf. | wc -c 'sono estremamente piccoli. La memorizzazione nella cache (ovvero se si esegue la stessa ricerca due volte sullo stesso albero) è molto più importante. IMHO la soluzione con "wc -l" è molto più intuitiva.
— pitseeker

4

Questa soluzione è certamente più lento rispetto ad alcune delle altre find -> wcsoluzioni qui, ma se si erano inclini a fare qualcosa di diverso con i nomi dei file, oltre a contarli, si poteva readdalla finduscita.

n=0
while read -r -d ''; do
    ((n++)) # count
    # maybe perform another act on file
done < <(find <expr> -print0)
echo $n

È solo una modifica di una soluzione trovata in BashGuide che gestisce correttamente i file con nomi non standard rendendo il finddelimitatore di output un byte NUL utilizzando print0e leggendo da esso utilizzando ''(byte NUL) come delimitatore di loop.


3

Questa è la mia countfilesfunzione nel mio ~/.bashrc(è ragionevolmente veloce, dovrebbe funzionare per Linux e FreeBSD finde non si lascia ingannare dai percorsi dei file contenenti caratteri di nuova riga; il finale wcconta solo NUL byte):

countfiles () 
{ 
   command find "${1:-.}" -type f -name "${2:-*}" -print0 | 
       command tr -dc '\0' | command wc -c;
return 0
}

countfiles

countfiles ~ '*.txt'
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.