find: -exec vs xargs (aka Tại sao lại tìm thấy |


10

Tôi đã cố gắng tìm tất cả các tệp thuộc một loại nhất định trải rộng trong các thư mục con và vì mục đích của tôi, tôi chỉ cần tên tệp. Tôi đã thử tước thành phần đường dẫn qua basename, nhưng nó không hoạt động với xargs:

$ find . -name '*.deb' -print | xargs basename 
basename: extra operand `./pool/main/a/aalib/libaa1_1.4p5-37+b1_i386.deb'
Try `basename --help' for more information.

Tôi nhận được điều tương tự (chính xác là cùng một lỗi) với một trong các biến thể sau:

$ find . -name '*.deb' -print0 | xargs -0 basename 
$ find . -name '*.deb' -print | xargs basename {}

Mặt khác, điều này hoạt động như mong đợi:

$ find . -name '*.deb' -exec basename {} \;
foo
bar
baz

Điều này xảy ra trên Cygwin và Debian 5.0.3 cập nhật. Chẩn đoán của tôi là xargs vì một lý do nào đó chuyển hai dòng đầu vào cho tên cơ sở, nhưng tại sao? Những gì đang xảy ra ở đây?

Câu trả lời:


23

Bởi vì basenamechỉ muốn một tham số ... không phải RẤT NHIỀU. Và xargstạo ra rất nhiều thông số.

Để giải quyết vấn đề thực sự của bạn (chỉ liệt kê tên tệp):

 find . -name '*.deb' -printf "%f\n"

Mà chỉ in 'tên cơ sở' (man find):

 %f     File's name with any leading directories
        removed (only the last element).

1
oooh .... / tát trán một lần nữa / tôi nghĩ rằng tôi cần một cuốn sách "tìm kiếm người giả" ...
quack quixote

Tôi nghĩ rằng vấn đề xargslà nó tạo ra một danh sách các đối số và cung cấp cho mỗi lệnh theo sau? Nếu không thì sự khác biệt giữa cái đó và find . -name '*.deb' | basenamecái gì?
WindowsMaker

GNU basename hiện có một -atùy chọn: "hỗ trợ nhiều đối số và coi mỗi đối số là một tên".
giám mục

1
@WindowsMaker xargschuyển đổi stdinthành các đối số lệnh. Theo một cách nào đó, nó ngược lại echo, chuyển đổi các đối số của nó thành stdout. Sự khác biệt giữa find ... | xargs -n1 basenamehoặc find ... | xargs basename -afind ... | basenamelà hai cái trước sẽ làm việc với việc thực hiện basenamebỏ qua đó stdin.
8bittree

19

Thử đi:

find . -name '*.deb' | xargs -n1 basename

Đây không phải là lời giải thích, đây là một cách giải quyết. và cách giải quyết cũng tốt như chỉ gọi 'basename' qua -exec cho bất kỳ tệp nào được tìm thấy.
akira

4
1 ... trong khi không một lời giải thích, điều này sẽ dẫn tôi để điều tra xargs chuyển bạn hiển thị, mà cuối cùng sẽ dẫn tôi đến chuyển động trán-tát tôi chỉ sử dụng đọc akira và john t của câu trả lời ...
quack quixote

1
Đây là cách tôi làm điều đó. Tôi không cảm thấy muốn học tất cả các phần trong và ngoài của findlệnh, vì vậy tôi chỉ sử dụng nó để tìm và liệt kê các tệp, và tôi sử dụng xargs cho mọi thứ khác.
Ryan C. Thompson

4

tên cơ sở chỉ chấp nhận một đối số duy nhất. Việc sử dụng -exechoạt động đúng bởi vì mỗi cái {}được thay thế bằng tên tệp hiện tại đang được xử lý và lệnh được chạy một lần cho mỗi tệp phù hợp , thay vì cố gắng gửi tất cả các đối số đến tên cơ sở trong một lần.


3

xargs cũng có thể bị buộc phải vượt qua một đối số ...

find . -name '*.deb' -print | xargs -n1 basename

Điều này hoạt động, tuy nhiên câu trả lời được chấp nhận đang sử dụng findtheo cách thích hợp hơn. Tôi thấy câu hỏi này đang tìm kiếm các xargs basenamevấn đề khi tôi đang sử dụng một lệnh khác để có danh sách các vị trí tệp. Các -n1lá cờ cho xargslà câu trả lời cuối cùng cho tôi.

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.