Tại sao xargs cần thiết?


25

Giả sử tôi muốn xóa tất cả các tệp trong một thư mục ngoại trừ một tệp có tên "Notes.txt". Tôi sẽ làm điều này với các đường ống , ls | grep -v "notes.txt" | xargs rm. Tại sao tôi cần xargs nếu đầu ra của ống thứ hai là đầu vào mà rm nên sử dụng?

Để so sánh, đường ống dẫn, echo "#include <knowledge.h>" | cat > foo.cchèn văn bản được lặp lại vào tệp mà không sử dụng xargs. Sự khác biệt giữa hai đường ống này là gì?


3
Bạn không nên sử dụng ls | grep -v "notes.txt" | xargs rmđể loại bỏ tất cả mọi thứ trừ notes.txt, hoặc nói chung, không bao giờ phân tích lsđầu ra . Lệnh của bạn sẽ bị hỏng nếu một tệp duy nhất chứa một khoảng trắng chẳng hạn. Cách an toàn hơn sẽ là rm !(notes.txt)Bash (với shopt -s extglobset) hoặc rm ^notes.txtZsh (with EXTENDED_GLOB), v.v.
slhck

Để tránh không gian bạn có thể làm find . -maxdepth 1 -mindepth 1 -print0 | xargs -0thay vì ls | xargs:-)
nổi

Câu trả lời:


35

Bạn đang nhầm lẫn hai loại đầu vào rất khác nhau: STDIN và đối số. Đối số là một danh sách các chuỗi được cung cấp cho lệnh khi nó bắt đầu, thường bằng cách chỉ định chúng sau tên lệnh (ví dụ echo these are some argumentshoặc rm file1 file2). STDIN, mặt khác, là một luồng byte (đôi khi là văn bản, đôi khi không) mà lệnh có thể (tùy chọn) đọc sau khi nó bắt đầu. Dưới đây là một số ví dụ (lưu ý catcó thể lấy đối số hoặc STDIN, nhưng nó thực hiện những điều khác nhau với chúng):

echo file1 file2 | cat    # Prints "file1 file2", since that's the stream of
                          # bytes that echo passed to cat's STDIN
cat file1 file2    # Prints the CONTENTS of file1 and file2
echo file1 file2 | rm    # Prints an error message, since rm expects arguments
                         # and doesn't read from STDIN

xargs có thể được coi là chuyển đổi đầu vào kiểu STDIN thành đối số:

echo file1 file2 | cat    # Prints "file1 file2"
echo file1 file2 | xargs cat    # Prints the CONTENTS of file1 and file2

echo thực tế thì ít nhiều ngược lại: nó chuyển đổi các đối số của nó thành STDOUT (có thể được dẫn đến một số STDIN của lệnh khác):

echo file1 file2 | echo    # Prints a blank line, since echo doesn't read from STDIN
echo file1 file2 | xargs echo    # Prints "file1 file2" -- the first echo turns
                                 # them from arguments into STDOUT, xargs turns
                                 # them back into arguments, and the second echo
                                 # turns them back into STDOUT
echo file1 file2 | xargs echo | xargs echo | xargs echo | xargs echo    # Similar,
                                 # except that it converts back and forth between
                                 # args and STDOUT several times before finally
                                 # printing "file1 file2" to STDOUT.

9

catlấy đầu vào từ STDINrmkhông. Đối với các lệnh như vậy, bạn cần xargslặp lại qua STDINtừng dòng và thực hiện các lệnh với các tham số dòng lệnh.

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.