tìm -exec + vs tìm | xargs: chọn cái nào?


32

Tôi hiểu rằng -execcó thể có một +tùy chọn để bắt chước hành vi của xargs. Có bất kỳ tình huống mà bạn thích một hình thức hơn hình thức khác?

Cá nhân tôi có xu hướng thích hình thức đầu tiên, nếu chỉ để tránh sử dụng một đường ống. Tôi chắc chắn các nhà phát triển findphải thực hiện các tối ưu hóa phù hợp. Tôi có đúng không?

Câu trả lời:


21

Bạn có thể muốn xâu chuỗi các cuộc gọi để tìm (một lần, khi bạn biết, điều đó là có thể, có thể là ngày hôm nay). Điều này, tất nhiên, chỉ có thể miễn là bạn ở lại tìm thấy. Một khi bạn chuyển sang xargs nó nằm ngoài phạm vi.

Ví dụ nhỏ, hai tệp a.lst và b.lst:

cat a.lst
fuddel.sh
fiddel.sh

cat b.lst
fuddel.sh

Không có mẹo ở đây - đơn giản là thực tế là cả hai đều chứa "fuddel" nhưng chỉ có một cái chứa "fiddel".

Giả sử chúng ta không biết điều đó. Chúng tôi tìm kiếm một tập tin phù hợp với 2 điều kiện:

find -exec grep -q fuddel {} ";" -exec grep -q fiddel {} ";" -ls
192097    4 -rw-r--r--   1 stefan   stefan         20 Jun 27 17:05 ./a.lst

Chà, có thể bạn biết cú pháp cho grep hoặc một chương trình khác để vượt qua cả hai chuỗi như điều kiện, nhưng đó không phải là vấn đề. Mọi chương trình có thể trả về đúng hoặc sai, được cung cấp một tệp làm đối số, có thể được sử dụng ở đây - grep chỉ là một ví dụ phổ biến.

Và lưu ý, bạn có thể làm theo tìm exec với lệnh find khác, như -ls hoặc -delete hoặc một cái gì đó tương tự. Lưu ý, việc xóa không chỉ rm (xóa tệp) mà còn rmdir (xóa thư mục).

Chuỗi như vậy được đọc dưới dạng kết hợp AND của các lệnh, miễn là không được chỉ định khác (cụ thể là với một -orcông tắc (và parens (cần che dấu))).

Vì vậy, bạn không rời khỏi chuỗi tìm kiếm, đó là một điều tiện dụng. Tôi không thấy bất kỳ lợi thế nào khi sử dụng -xargs, vì bạn phải cẩn thận trong việc truyền các tệp, đây là điều không cần làm - nó tự động xử lý chuyển từng tệp dưới dạng một đối số cho bạn.

Nếu bạn tin rằng bạn cần một số mặt nạ để tìm {} niềng răng , vui lòng truy cập câu hỏi của tôi để yêu cầu bằng chứng. Khẳng định của tôi là: Bạn không.


3
Bài đăng này đã mở mắt cho tôi một cách sử dụng mới find. Cảm ơn rất nhiều!
rahmu

1
"Tôi không thấy bất kỳ lợi thế nào trong việc sử dụng -xargs". Là gì -execcách để làm xargs -P4sao cho ba trong số bốn lõi không ở lại nhàn rỗi?
Damian Yerrick

1
@DamianYerrick: Kết thúc lệnh -exec không có trong ";" nhưng với dấu + (/ dấu cộng).
người dùng không xác định

25

Tên tập tin đường ống an toàn để xargsyêu cầu bạn findhỗ trợ -print0tùy chọn và bạn xargscó tùy chọn tương ứng để đọc nó ( --nullhoặc -0). Mặt khác, tên tệp có ký tự không thể in hoặc dấu gạch chéo ngược hoặc dấu ngoặc kép hoặc khoảng trắng trong tên có thể gây ra hành vi không mong muốn. Mặt khác, find -exec {} +là trong POSIX findđặc tả , vì vậy nó là xách tay, và đó là về an toàn như find -print0 | xargs -0, và chắc chắn an toàn hơn find | xargs. Tôi khuyên bạn không bao giờ nên làm find | xargsmà không có -print0.


6
Một ngoại lệ đáng chú ý về tính di động của find … -exec … {} +OpenBSD, chỉ có được tính năng này với phiên bản 5.1 được phát hành vào năm 2012. Tất cả các BSD đã có -print0trong vài năm, thậm chí OpenBSD (mặc dù nó cũng chống lại tính năng đó trong một thời gian). Solaris, mặt khác, dính vào các tính năng POSIX, vì vậy bạn có -exec +và không -print0.
Gilles 'SO- ngừng trở nên xấu xa'

-print0là một nỗi đau và mặc dù bạn có thể tranh luận xargs --delimiter "\n"là không tương đương, tôi chưa bao giờ sử dụng cái trước sau khi khám phá cái sau.
Sridhar Sarnobat

3
Tôi không thấy làm thế nào -0là một nỗi đau hơn --delimiter "\n".
jw013

2
Ngoài ra -0, GNU xargscần -rtránh chạy lệnh nếu không có đầu vào.
Stéphane Chazelas

2
Một vấn đề khác | xargs -r0 cmdcmdstdin của nó bị ảnh hưởng (tùy thuộc vào việc xargsthực hiện, đó là /dev/nullđường ống.
Stéphane Chazelas

10

Nếu bạn sử dụng -exec ... ;biểu mẫu (ghi nhớ để thoát dấu chấm phẩy), bạn đang chạy lệnh một lần cho mỗi tên tệp. Nếu bạn sử dụng -print0 | xargs -0, bạn chạy nhiều lệnh cho mỗi tên tệp. Bạn chắc chắn nên sử dụng -exec +biểu mẫu, đặt nhiều tệp trong một dòng lệnh và nhanh hơn nhiều khi có một số lượng lớn tệp được tham gia.

Một điểm cộng lớn của việc sử dụng xargslà khả năng chạy song song nhiều lệnh xargs -P. Trên các hệ thống đa lõi, điều đó có thể cung cấp tiết kiệm thời gian rất lớn.


6
Bạn có nghĩa là -Pthay vì -p. Hãy nhớ rằng xargs -Pkhông phải trong tiêu chuẩn POSIX, trong khi đó find -exec {} +, điều này rất quan trọng nếu bạn chuẩn bị cho tính di động.
jw013

@Alexios Bạn không cần phải thoát dấu cộng, bởi vì nó không có ý nghĩa đặc biệt cho shell: find /tmp/ -exec ls "{}" +hoạt động tốt.
daniel kullmann

1
Tất nhiên là đúng. Tôi đã trốn thoát mọi thứ sau một -execthời gian dài (Tôi là một masochist, tôi thậm chí không sử dụng dấu ngoặc kép để trốn thoát {}, tôi luôn gõ \{\}; đừng hỏi), mọi thứ dường như phải được thoát ra ngay bây giờ.
Alexios

1
@Alexios: Nếu bạn tìm thấy một ví dụ (ngoại trừ việc là một masochist) trong đó việc đeo mặt nạ niềng răng là hữu ích, vui lòng cung cấp nó như một câu trả lời cho câu hỏi của tôi ở đây - afaik gợi ý này đã lỗi thời và chỉ là một bản sao trong trang. Tôi chưa bao giờ thấy một ví dụ nơi find /tmp/ -exec ls {} +sẽ không làm việc.
người dùng không xác định

1
Đối với tôi, đây là bộ nhớ cơ được hình thành từ thời SunOS 4. Vì tôi đã làm điều đó trong nhiều năm, tôi hoàn toàn không nhận thấy khi bashbắt đầu chấp nhận nguyên văn niềng răng. Tôi khá chắc chắn rằng ít nhất một trong những chiếc vỏ cũ mà tôi đã sử dụng đã phù hợp với tiếng rít nếu niềng răng không thoát ra được.
Alexios

8

Liên quan đến hiệu suất Tôi nghĩ rằng -exec … +đơn giản là sẽ tốt hơn vì đó là một công cụ duy nhất thực hiện tất cả công việc nhưng một phần trong tài liệu của GNU findutil nói rằng -exec … +có thể kém hiệu quả hơn trong một số trường hợp:

[tìm với -exec … +] có thể kém hiệu quả hơn một số cách sử dụng xargs; ví dụ xargscho phép các dòng lệnh mới được xây dựng trong khi lệnh trước đó vẫn đang thực thi và cho phép bạn chỉ định một số lệnh để chạy song song. Tuy nhiên, find ... -exec ... +cấu trúc có lợi thế về tính di động rộng. GNU findutils không hỗ trợ ' -exec ... +' cho đến phiên bản 4.2.12 [tháng 1 năm 2005] ; một trong những lý do cho điều này là nó đã có -print0hành động '' trong mọi trường hợp.

Tôi không chắc chính xác điều đó có nghĩa gì nên tôi đã hỏi trong cuộc trò chuyện nơi derobert giải thích nó là:

findcó thể có thể tiếp tục tìm kiếm lô tệp tiếp theo trong khi -exec … +đang chạy, nhưng không được.
find … | xargs …bởi vì sau đó tìm thấy là một quá trình khác nhau và nó tiếp tục chạy cho đến khi bộ đệm ống đầy lên

(Định dạng của tôi.)

Vì vậy, có đó. Nhưng nếu hiệu suất thực sự quan trọng, bạn sẽ phải thực hiện đo điểm chuẩn thực tế hoặc thậm chí tự hỏi liệu bạn thậm chí có muốn sử dụng shell cho các trường hợp như vậy không.

Ở đây trên trang này tôi nghĩ tốt hơn là nên khuyên mọi người sử dụng -exec … +biểu mẫu bất cứ khi nào có thể bởi vì nó đơn giản hơn và vì những lý do được đề cập trong các câu trả lời khác ở đây (ví dụ: xử lý tên tệp lạ mà không phải suy nghĩ nhiều).

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.