79

Пример:

ls | echo ничего не печатает (на самом деле пустая строка). Я ожидаю, что это напечатает список файлов.

ls | grep 'foo' , с другой стороны, работает как положено (печатает файлы с именем 'foo').

В этих ситуациях я делаю что-то вроде:ls | while read OUT; do echo $OUT; done но это довольно громоздко.

Почему конвейер работает с некоторыми командами, а не с другими? Как я могу обойти эту проблему?

4 ответа4

111

Существует различие между аргументами командной строки и стандартным вводом. Канал соединит стандартный вывод одного процесса со стандартным вводом другого. Так

ls | echo

Подключает стандартный вывод ls к стандартному вводу эха. Хорошо верно? Что ж, echo игнорирует стандартный ввод и выводит свои аргументы командной строки (которых в данном случае нет) в свой собственный стандартный вывод. Выход: вообще ничего.

В этом случае есть несколько решений. Одним из них является использование команды, которая читает stdin и создает дамп в stdout, например, cat.

ls | cat

Будет «работать», в зависимости от вашего определения работы.

Но как насчет общего случая. Что вам действительно нужно, так это преобразовать стандартный вывод одной команды в аргументы командной строки другой. Как уже говорили другие, xargs в этом случае является каноническим вспомогательным инструментом, считывая аргументы командной строки для команды из своего стандартного ввода и создавая команды для запуска.

ls | xargs echo

Вы также можете преобразовать это, используя команду подстановки $()

echo $(ls)

Также будет делать то, что вы хотите.

Оба эти инструмента являются ядром сценариев оболочки, вы должны изучить оба.

Для полноты, как вы указали в вопросе, другой базовый способ преобразования stdin в аргументы командной строки - встроенная в оболочку команда read . Он преобразует "слова" (слова, как определено в переменной IFS ) во временную переменную, которую вы можете использовать при любом запуске команды.

17

ls | echo выводит только пустую строку, потому что echo читает ввод; последняя команда конвейера на самом деле - echo которая печатает только пустую строку.

В общем-то:

a | b

удостоверяется, что выход a становится входом b . Я предлагаю вам прочитать раздел Pipelines man bash .


Если вы действительно хотите использовать ls и echo вместе, вот несколько (довольно бесполезных) примеров:

ls | xargs -L 1 echo
echo `ls`
for i in `ls` ; do echo $i ; done
8

Если вы хотите echo команду ls попробуйте:

ls | xargs echo

Это вызовет echo с выводом ls .

3

Почему бы просто не использовать:

echo `ls`

Или намного безопаснее:

echo "`ls -lrt`"

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