2009-05-22 42 views
100

Cái nào hiệu quả hơn trên một tập hợp rất lớn các tệp và nên được sử dụng?find -exec cmd {} + vs | xargs

find . -exec cmd {} + 

hoặc

find . | xargs cmd 

(Giả sử rằng không có nhân vật hài hước trong tên tập tin)

+0

Related: https://stackoverflow.com/questions/9612090/how-to-loop-through-file-names-returned-by-find –

Trả lời

94

Chênh lệch tốc độ sẽ không đáng kể.

Nhưng bạn phải chắc chắn rằng:

  1. kịch bản của bạn sẽ không giả định rằng không có tập tin sẽ có không gian, tab, vv trong tên file; phiên bản đầu tiên là an toàn, phiên bản thứ hai thì không.

  2. Tập lệnh của bạn sẽ không xử lý tệp bắt đầu bằng "-" làm tùy chọn.

Vì vậy, mã của bạn sẽ trông như thế này:

find . -exec cmd -option1 -option2 -- {} + 

hoặc

find . -print0 | xargs -0 cmd -option1 -option2 -- 

Phiên bản đầu tiên là ngắn hơn và dễ dàng hơn để viết như bạn có thể bỏ qua 1, nhưng phiên bản thứ hai là di động và an toàn hơn, vì "-exec cmd {} +" là một tùy chọn tương đối mới trong các bản tìm kiếm GNU (từ năm 2005, nhiều hệ thống đang chạy sẽ chưa có) và nó là buggy recently. Rất nhiều người không biết điều này "-exec cmd {} +", như bạn có thể thấy từ các câu trả lời khác.

+4

-print0 cũng là một tùy chọn tìm GNU (và GNU xargs) bị thiếu từ rất nhiều hệ thống không phải Linux, do đó, đối số di động không hợp lệ.Chỉ sử dụng dấu vân tay và để lại -0 off xargs, tuy nhiên, * là * rất di động. – dannysauer

+4

Vấn đề là không có -print0 nó không hoạt động nếu có một tập tin với một không gian hoặc tab vv. Điều này có thể là một lỗ hổng bảo mật như thể có một tên tập tin như "foo -o index.html" sau đó -o sẽ được được coi là một lựa chọn. Hãy thử trong thư mục trống: "touch - foo \ -o \ index.html; tìm thấy. | Xargs cat". Bạn sẽ nhận được: "mèo: tùy chọn không hợp lệ - 'o'" – Tometzky

+2

Ví dụ của ông là tên tệp chứa a -. Nếu không có -print0, tìm sẽ nhổ ra ./foo -o index.html. Vì vậy, có thể bắt đầu với một - không phải là một vấn đề lớn, nhưng kết quả là ít thay đổi, và trên một hệ thống đa người dùng, có thể cung cấp một vector tấn công nếu kịch bản của bạn là thế giới có thể đọc được. – bobpaul

7
find . | xargs cmd 

là hiệu quả hơn (nó chạy cmd càng ít lần càng tốt, không giống như exec, chạymột lần cho mỗi trận đấu). Tuy nhiên, bạn sẽ gặp rắc rối nếu tên tập tin chứa dấu cách hoặc ký tự funky.

Sau đây là gợi ý để được sử dụng:

find . -print0 | xargs -0 cmd 

này sẽ làm việc ngay cả khi tên tập tin chứa các ký tự funky (-print0 làm find trận in NUL-chấm dứt, -0 làm xargs mong đợi định dạng này.)

+25

Đây không phải là "find. -exec cmd {} \;" nhưng "find. -exec cmd {} +". Sau này sẽ không chạy một tập tin tại một thời điểm. – Tometzky

+2

Lưu ý rằng phương pháp 'xargs' thực sự chậm hơn đáng kể nếu không có (hoặc chỉ một vài) tệp phù hợp và' cmd' không có nhiều việc phải làm cho mỗi tệp. Ví dụ, khi chạy trong một thư mục trống, phiên bản 'xargs' sẽ mất ít nhất hai lần thời gian, vì hai tiến trình phải được bắt đầu thay vì chỉ một. (Có, sự khác biệt thường không thể nhận thấy trên * nix, nhưng trong vòng lặp nó có thể quan trọng; hoặc, hãy thử trên Windows một thời gian ...) – SamB

Các vấn đề liên quan