tìm -exec cmd {} + vs | xargs


Câu trả lời:


107

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

Nhưng bạn phải đảm bảo rằng:

  1. Tập lệnh của bạn sẽ không cho rằng không có tệp nào có khoảng trắng, tab, v.v. trong tên tệp; 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 coi tệp bắt đầu bằng " -" là một tùy chọn.

Vì vậy, mã của bạn sẽ giống như sau:

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

hoặc là

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

Phiên bản đầu tiên ngắn hơn và dễ viết hơn vì bạn có thể bỏ qua phiên bản 1, nhưng phiên bản thứ hai mang tính di động và an toàn hơn, vì " -exec cmd {} +" là một tùy chọn tương đối mới trong GNU findutils (kể từ năm 2005, rất nhiều hệ thống đang chạy sẽ chưa có) và nó đã bị lỗi gần đây . Cũng có 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 GNU find (và GNU xargs) bị thiếu trong nhiều hệ thống không phải Linux, vì vậy đối số khả năng di chuyển không hợp lệ. Sử dụng chỉ -print và rời khỏi -0 tắt của xargs, tuy nhiên, rất cầm tay.
dannysauer

7
Vấn đề là không có -print0 thì nó không hoạt động nếu có tệp có khoảng trắng hoặc tab, v.v. Đây có thể là một lỗ hổng bảo mật vì nếu có tên tệp như "foo -o index.html" thì -o sẽ được xử lý Như là một lựa chọn. Hãy thử trong thư mục trống: "touch - foo \ -o \ index.html; find. | Xargs cat". Bạn sẽ nhận được: "cat: tùy chọn không hợp lệ - 'o'"
Tometzky

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

2
Một ghi chú về điều gì đó đã khiến tôi vấp phải ở đây - việc sử dụng execsẽ xuất ra kết quả khi chúng được tìm thấy, xargscó vẻ như, sẽ đợi cho đến khi toàn bộ thư mục được tìm kiếm trước khi ghi vào stdout. Nếu bạn đang thử điều này trên một thư mục lớn và có vẻ như xargskhông hiệu quả, bạn nên kiên nhẫn.
FarmerGedden

1
@Motiised Without -print0find trả về các tên tệp được phân tách bằng dòng mới, nhưng dòng mới cũng có thể là một phần của tên tệp, khiến nó trở nên mơ hồ. Byte 0 không thể, vì vậy nó là một dấu phân cách an toàn. Có - thêm --vào một lệnh hỗ trợ nó là một thực tiễn tốt khi bạn không thể kiểm soát các đối số của nó, ngay cả khi không phải lúc nào cũng được yêu cầu nghiêm ngặt hoặc không an toàn.
Tometzky

7
find . | xargs cmd

hiệu quả hơn (nó chạy cmdít lần nhất có thể, không giống như execchạy cmdmộ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 chứa khoảng trắng hoặc ký tự vui nhộn.

Những điều sau đây được đề xuất sử dụng:

find . -print0 | xargs -0 cmd

điều này sẽ làm việc ngay cả khi tên tập tin chứa các ký tự funky ( -print0làm cho findin trận NUL-chấm dứt, -0làm cho xargshy vọng định dạng này.)


28
Đây không phải là "tìm. -Exec cmd {} \;" nhưng "tìm. -exec cmd {} +". Sau này sẽ không chạy từng tệp một.
Tometzky

2
Lưu ý rằng xargsphương pháp này 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à cmdkhô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, xargsphiên bản sẽ mất ít nhất gấp đôi thời gian, vì phải khởi động hai quá trình thay vì chỉ một. (Vâng, sự khác biệt là thường không thể nhận thấy trên * nix, nhưng trong một vòng lặp nó có thể là quan trọng; hoặc, hãy thử nó trên Windows một thời gian ...)
Samb

2

Các xargsphiên bản hiện đại thường hỗ trợ thực thi đường ống song song.

Rõ ràng nó có thể là một điểm mấu chốt khi phải lựa chọn giữa find … -exec… | xargs

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.