20

Предположим, я хочу удалить все файлы в каталоге, кроме одного с именем "notes.txt". Я бы сделал это с конвейером, ls | grep -v "notes.txt" | xargs rm . Зачем мне нужен xargs, если на выходе второго канала указан вход, который должен использовать rm?

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

2 ответа2

31

Вы путаете два очень разных вида ввода: 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.
8

cat принимает входные данные от STDIN а rm - нет. Для таких команд вам нужно, чтобы xargs перебирал STDIN построчно и выполнял команды с параметрами командной строки.

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .