Apa cara terbaik untuk menghitung hasil "temukan"?

102

Solusi saya saat ini adalah find <expr> -exec printf '.' \; | wc -c, tetapi ini memakan waktu terlalu lama ketika ada lebih dari 10.000 hasil. Apakah tidak ada cara yang lebih cepat / lebih baik untuk melakukan ini?

MechMK1
sumber
gunakan wc -l pada hasil pencarian Anda
Manuel Selva

Jawaban:

89

Coba ini sebagai gantinya (membutuhkan find's -printfdukungan):

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

Ini akan lebih dapat diandalkan dan lebih cepat daripada menghitung garis.

Perhatikan bahwa saya menggunakan find's printf, bukan perintah eksternal.


Mari bangku sedikit:

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

Tolok ukur cuplikan saya:

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

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

Dengan garis penuh:

$ time find -type f | wc -l
8

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

Jadi solusi saya lebih cepat =) (bagian yang penting adalah realgaris)

Gilles Quenot
sumber
6
Tidak setara, ini lebih dapat diandalkan =)
Gilles Quenot
6
Ini tidak lebih dapat diandalkan jika tanda -printf untuk menemukan tidak didukung di platform Anda. ;-)
Randy Howard
9
Perhatikan bahwa Anda dapat memangkas beberapa nanodetik lagi dengan tidak mengutip titik dalam-printf '.'
Jens
6
@Jens - terutama ketika Anda memperhitungkan waktu yang dibutuhkan untuk mengetik itu
Brian Agnew
7
Dengan patokan sekecil itu, pengaturan waktu mungkin didominasi oleh faktor lain selain yang ingin Anda ukur. Percobaan dengan pohon besar akan lebih bermanfaat. Tapi ini membuat saya memilih untuk benar-benar melakukan apa yang diminta OP.
tripleee
134

Kenapa tidak

find <expr> | wc -l

sebagai solusi portabel sederhana? Solusi asli Anda menghasilkan proses baru printf untuk setiap file yang ditemukan, dan itu sangat mahal (seperti yang baru saja Anda temukan).

Perhatikan bahwa ini akan berlebihan jika Anda memiliki nama file dengan baris baru yang disematkan, tetapi jika Anda memilikinya maka saya curiga masalah Anda berjalan sedikit lebih dalam.

Brian Agnew
sumber
10
-1: akan merusak file dengan baris baru, dan ini lebih lambat daripada menghitung byte =)
Gilles Quenot
24
Saya rasa tidak perlu downvote karena batasan nama file / baris baru cukup langka dan disebutkan di atas. Lebih lambat ? Mungkin. Mengingat Anda menanyakan sistem file, saya menduga perbedaan kecepatannya kecil. Di 10.000 file saya, saya mengukur perbedaan 3ms
Brian Agnew
9
Perbedaan kinerja antara 'find <expr> | wc -l' dan 'find <expr> -printf. | wc -c 'sangat kecil. Caching (yaitu jika Anda menjalankan pencarian yang sama dua kali pada pohon yang sama) jauh lebih penting. IMHO, solusi dengan "wc -l" jauh lebih intuitif.
pitseeker
5

Solusi ini tentu saja lebih lambat daripada beberapa find -> wcsolusi lain di sini, tetapi jika Anda cenderung melakukan hal lain dengan nama file selain menghitungnya, Anda bisa readdari findoutput.

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

Ini hanyalah modifikasi dari solusi yang ditemukan di BashGuide yang menangani file dengan nama yang tidak standar dengan benar dengan membuat findpembatas output menjadi byte NUL menggunakan print0, dan membacanya menggunakan ''(NUL byte) sebagai pembatas loop.

John B
sumber
4

Ini adalah countfilesfungsi saya di saya ~/.bashrc(ini cukup cepat, seharusnya berfungsi untuk Linux & FreeBSD find, dan tidak tertipu oleh jalur file yang berisi karakter baris baru; yang terakhir wchanya menghitung byte NUL):

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

countfiles

countfiles ~ '*.txt'
carlo
sumber