Чому потрібні xargs?


25

Припустимо, я хочу видалити всі файли в каталозі, крім одного з назвою "notes.txt". Я хотів би зробити це з допомогою трубопроводу ls | grep -v "notes.txt" | xargs rm. Навіщо мені потрібні xargs, якщо вихід другої труби є входом, який повинен використовувати rm?

Для порівняння, конвеєр echo "#include <knowledge.h>" | cat > foo.cвставляє відтворений текст у файл без використання xargs. Яка різниця між цими двома трубопроводами?


3
Ви не повинні використовувати ls | grep -v "notes.txt" | xargs rmдля видалення всього, окрім notes.txt, або взагалі ніколи не аналізувати lsвихід . Ваша команда порушиться, якщо, наприклад, у одному файлі міститься пробіл. Більш безпечним способом було б rm !(notes.txt)в Bash (з shopt -s extglobнабором), або rm ^notes.txtв Zsh (з EXTENDED_GLOB) тощо
slhck

Щоб уникнути пробілів, ви можете зробити find . -maxdepth 1 -mindepth 1 -print0 | xargs -0замість ls | xargs:-)
flob

Відповіді:


35

Ви плутаєте два дуже різні види введення: STDIN та аргументи. Аргументи - це список рядків, що надаються команді під час її запуску, зазвичай, вказуючи їх після імені команди (наприклад, echo these are some argumentsабо rm file1 file2). З іншого боку, STDIN - це потік байтів (іноді текст, іноді ні), який команда може (необов'язково) читати після її запуску. Ось кілька прикладів (зауважте, що catможна брати аргументи або STDIN, але це робить різні речі з ними):

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 можна вважати перетворенням введення стилю STDIN в аргументи:

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

echo насправді робить більш-менш навпаки: він перетворює свої аргументи в STDOUT (що може бути передано в STDIN іншої команди):

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

catприймає вхід STDINі rmне робить. Для таких команд потрібно xargsперебирати STDINрядки за рядком і виконувати команди з параметрами командного рядка.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.