Cách tốt nhất để đếm kết quả "tìm thấy" là gì?


99

Giải pháp hiện tại của tôi sẽ là find <expr> -exec printf '.' \; | wc -c, nhưng điều này mất quá nhiều thời gian khi có hơn 10000 kết quả. Không có cách nào nhanh hơn / tốt hơn để làm điều này?


sử dụng -l wc trên kết quả tìm bạn
Manuel Selva

Câu trả lời:


84

Hãy thử điều này thay vì (yêu cầu find's -printfhỗ trợ):

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

Nó sẽ đáng tin cậy hơn và nhanh hơn so với việc đếm các dòng.

Lưu ý rằng tôi sử dụng lệnh find's printf, không phải lệnh bên ngoài.


Hãy băng ghế một chút:

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

Điểm chuẩn đoạn mã của tôi:

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

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

Với đầy đủ các dòng:

$ time find -type f | wc -l
8

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

Nên cách giải của mình nhanh hơn =) (phần quan trọng là realdòng)


6
Không tương đương, đó là đáng tin cậy hơn =)
Gilles Quenot

6
Sẽ không đáng tin cậy hơn nếu cờ -printf cần tìm không được hỗ trợ trên nền tảng của bạn. ;-)
Randy Howard,

7
Lưu ý rằng bạn có thể giảm thêm vài nano giây nữa bằng cách không trích dẫn dấu chấm trong-printf '.'
Jens

6
@Jens - đặc biệt là khi bạn đưa vào tài khoản thời gian thực hiện để gõ mà
Brian Agnew

6
Với một tiêu chuẩn nhỏ như vậy, thời gian có thể bị chi phối bởi các yếu tố khác ngoài thứ bạn muốn đo. Thử nghiệm với một cái cây lớn sẽ hữu ích hơn. Nhưng điều này nhận được phiếu bầu của tôi vì đã thực sự làm những gì OP yêu cầu.
tripleee

133

Tại sao không

find <expr> | wc -l

như một giải pháp di động đơn giản? Giải pháp ban đầu của bạn đang tạo ra một quy trình mới printf cho mọi tệp riêng lẻ được tìm thấy và điều đó rất tốn kém (như bạn vừa tìm thấy).

Lưu ý rằng điều này sẽ vượt quá nếu bạn có các tên tệp có nhúng dòng mới, nhưng nếu bạn có tên tệp đó thì tôi nghi ngờ sự cố của bạn sẽ sâu hơn một chút.


9
-1: sẽ phá vỡ trong hồ sơ với dòng mới, và đó là chậm hơn so với đếm byte =)
Gilles Quenot

21
Tôi không nghĩ rằng điều đó đảm bảo một sự phản đối vì giới hạn tên tệp / dòng mới là khá hiếm đã được lưu ý ở trên. Chậm hơn ? Có lẽ. Vì bạn đang truy vấn hệ thống tệp, tôi nghi ngờ sự khác biệt về tốc độ là nhỏ. Across 10.000 tác phẩm của tôi Tôi đo lường sự khác biệt 3ms
Brian Agnew

8
Sự khác biệt về hiệu suất giữa 'find <expr> | wc -l' và 'find <expr> -printf. | wc -c 'là cực kỳ nhỏ. Lưu vào bộ nhớ đệm (tức là nếu bạn chạy cùng một tìm hai lần trên cùng một cây) quan trọng hơn nhiều. IMHO giải pháp với "wc -l" trực quan hơn rất nhiều.
pitseeker

4

Đây là countfileschức năng của tôi trong của tôi ~/.bashrc(nó khá nhanh, hoạt động cho Linux & FreeBSD findvà không bị đánh lừa bởi các đường dẫn tệp chứa các ký tự dòng mới; cuối cùng wcchỉ tính NUL byte):

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

countfiles

countfiles ~ '*.txt'

4

Giải pháp này chắc chắn chậm hơn một số find -> wcgiải pháp khác ở đây, nhưng nếu bạn có xu hướng làm điều gì đó khác với tên tệp ngoài việc đếm chúng, bạn có thể readtừ findđầu ra.

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

Nó chỉ là một sửa đổi của một giải pháp được tìm thấy trong BashGuide để xử lý đúng cách các tệp có tên không chuẩn findbằng cách sử dụng dấu phân cách đầu ra thành byte NUL print0và đọc từ đó bằng cách sử dụng ''(byte NUL) làm dấu phân cách vòng lặp.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.