Як передавати команди на інші команди?


83

Приклад:

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

ls | grep 'foo'з іншого боку, працює як очікувалося (друкує файли із написом "foo").

Те, що я роблю в цих ситуаціях, є чимось на кшталт: ls | while read OUT; do echo $OUT; doneале це досить громіздко.

Чому трубопровід працює з одними командами, а не з іншими? Як я можу обійти це питання?


2
Що ви очікуєте ls | echoзробити? чому б просто не бігти ls?
theomega

12
Я використав найпростіший приклад, який ілюструє мою думку. Я фактично зіткнувся з цією проблемою, коли я намагався зробити однолінійку, яка б відображала об’єкти git у магазині об'єктів та їх тип. Отже, я записав ідентифікатор об'єкта git cat-file, але він просто не працював. Мабуть, ехо має таку саму поведінку, тому я використав це як приклад.
Михай Ротару

також подивіться на команду -n для xargs, в ній сказано, скільки аргументів слід поставити на підкоманду. `... | xargs -n1 git cat-file`
Rich

Відповіді:


118

Існує відмінність між аргументами командного рядка та стандартним введенням. Труба з'єднає стандартний вихід одного процесу зі стандартним входом іншого. Тому

ls | echo

Підключає стандартний вихід ls до стандартного вводу ехо. Чудово правильно? Ну, echo ігнорує стандартне введення та скидає аргументи командного рядка - яких у цьому випадку немає - власного stdout. Вихід: взагалі нічого.

У цьому випадку є кілька рішень. Одне полягає у використанні команди, яка читає stdin та dump для stdout, наприклад cat.

ls | cat

Чи буде "працювати", залежно від того, яке ваше визначення роботи.

А як щодо загальної справи. Те, що вам справді хочеться, це перетворити stdout однієї команди в аргументи командного рядка іншої. Як вже говорили інші, чи xargsє в цьому випадку канонічним допоміжним інструментом, читаючи аргументи командного рядка для команди зі свого stdin та будуючи команди для запуску.

ls | xargs echo

Ви також можете це перетворити за допомогою команди підстановки $()

echo $(ls)

Також робиш те, що хочеш.

Обидва ці інструменти є ядром сценаріїв оболонок, ви повинні навчитися обом.

Для повноти, як ви вказуєте в питанні, інший базовий спосіб перетворення stdin в аргументи командного рядка - це вбудована readкоманда оболонки . Він перетворює "слова" (слова, визначені IFSзмінною), в змінну temp, яку ви можете використовувати в будь-яких командах.


1
Дуже корисна інформативна відповідь, дякую! Зараз я вивчаю баш, і раніше я бачив і xargs, і позначення $ (*), але не звертав на них особливої ​​уваги. Тепер я знаю, наскільки вони важливі, і обов'язково загляну в них.
Михай Ротару

1
xargs, можливо, був те, що шукав ОП.
Іктис

19

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


3

Чому б просто не використовувати:

echo `ls`

Або набагато безпечніше:

echo "`ls -lrt`"

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