Mengapa xargs diperlukan?

25

Misalkan saya ingin menghapus semua file dalam direktori kecuali untuk yang bernama "notes.txt". Saya akan melakukan ini dengan pipa ls | grep -v "notes.txt" | xargs rm,. Mengapa saya perlu xargs jika output dari pipa kedua adalah input yang harus digunakan rm?

Demi perbandingan, pipeline, echo "#include <knowledge.h>" | cat > foo.cmenyisipkan teks yang digaungkan ke dalam file tanpa menggunakan xargs. Apa perbedaan antara kedua jalur pipa ini?

seewalker
sumber
3
Anda seharusnya tidak menggunakan ls | grep -v "notes.txt" | xargs rmuntuk menghapus semuanya kecuali notes.txt, atau secara umum, tidak pernah menguraikan lsoutput . Perintah Anda akan rusak jika satu file berisi spasi, misalnya. Cara yang lebih aman adalah rm !(notes.txt)di Bash (dengan shopt -s extglobset), atau rm ^notes.txtdi Zsh (dengan EXTENDED_GLOB) dll.
slhck
Untuk menghindari ruang yang bisa Anda lakukan find . -maxdepth 1 -mindepth 1 -print0 | xargs -0alih - alih ls | xargs:-)
flob

Jawaban:

35

Anda membingungkan dua jenis input yang sangat berbeda: STDIN dan argumen. Argumen adalah daftar string yang disediakan untuk perintah saat dimulai, biasanya dengan menentukan mereka setelah nama perintah (misalnya echo these are some argumentsatau rm file1 file2). STDIN, di sisi lain, adalah aliran byte (kadang-kadang teks, kadang-kadang tidak) yang perintahnya dapat (secara opsional) membaca setelah dimulai. Berikut adalah beberapa contoh (catatan yang catdapat mengambil argumen atau STDIN, tetapi ada bedanya dengan mereka):

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 dapat dianggap sebagai mengubah input gaya STDIN ke argumen:

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

echo sebenarnya melakukan lebih atau kurang sebaliknya: ia mengubah argumennya menjadi STDOUT (yang dapat disalurkan ke STDIN beberapa perintah lain):

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.
Gordon Davisson
sumber
9

catmenerima input dari STDINdan rmtidak. Untuk perintah seperti itu Anda perlu xargsmengulang melalui STDINbaris demi baris dan menjalankan perintah dengan parameter baris perintah.

Alex P.
sumber