Понимание того, как входы отправляются на каналы в Bash

17

Я не совсем понимаю, как трубы работают в Bash.

Я знаю, что он принимает вывод одной команды в качестве ввода другой команды.

Какой вывод я могу получить, потому что это то, что команда выводит на экран.

Но как мне узнать, какой ввод примет команда?

Вот пример, который я думал, будет работать:

which gem | rm

К сожалению это не так.

Какой драгоценный камень распечатывается /usr/bin/gemтак, что должен быть правильный вывод?

Я думал, что это было дано г-ну, так будет, rm /usr/bin/gemно я ошибался.

Итак, мой вопрос: как мне узнать, какой ввод принимает команда?

ajsie
источник
2
Помимо всего прочего, rm /usr/bin/gemэто ужасная идея. Оставьте это gem(и Ruby-интерпретатор, с которым он идет) в покое и установите предпочитаемый Ruby-интерпретатор (и gem), используя rvm: rvm.beginrescueend.com
Telemachus

Ответы:

23

«Ввод» и «аргументы командной строки» - разные вещи.

rm удаляет файлы, представленные в качестве аргументов.

Канал перенаправляет вывод левой команды на ввод правой команды. Это не влияет на аргументы командной строки программы справа.

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

which gem | xargs rmНапример, удалит gemв вашем PATH.

Borealid
источник
12

rmне принимает входные данные, он принимает аргументы. Это разные. Аргументы - это ключи, имена файлов и т. Д., Которые вы передаете программе в командной строке, чтобы повлиять на ее поведение. Ввод - это данные, над которыми работает программа. Например,grep принимает как входные данные, так и аргументы:

grep "foo" file.txt

Там есть два аргумента "foo"и file.txt. Ввода является содержимым из file.txt, а не строкfile.txt самого. Поскольку grep принимает данные, вы можете использовать их с конвейерами:

cat file.txt | grep "foo"

производит тот же вывод, так как cat принимает file.txtв качестве аргумента и производит содержимоеfile.txt выводит в качестве вывода. Затем этот вывод передается в grep, что дает тот же эффект, что и сам grep, как в первом примере.

Если вы хотите использовать выходные данные одной программы в качестве аргумента другой, используйте обратные пометки:

rm `which gem`

или этот альтернативный (специфичный для bash) синтаксис:

rm $(which gem)

Изменить: или, xargsкак указывает другой ответчик. Множество способов убрать кошку из командной строки.

Тайлер МакГенри
источник
Стоит отметить, что cat file.txt | grep "foo"может быть в сотни раз медленнее, чем grep "foo" file.txt.
Бореалид
1
это та часть, которую я не понимаю. Как я узнаю, что такое аргумент и что такое стандартный ввод?
Ajsie
8
@ajsie: если вы набираете его после имени программы и перед нажатием Enter, это аргумент. Если вы вводите его в программу после запуска, это стандартный ввод.
Бореалид
1
Понял! Это все объяснило. Теперь я знаю, что могу использовать команду напрямую и посмотреть, подсказывает ли она мне (grep), и я мог бы также прочитать руководство (man grep), чтобы увидеть, использует ли оно ввод std.
Ajsie
@ajsie: Если вы не хотите погружаться в справочную страницу, есть также grep --helpкраткий обзор принятых аргументов.
Бореалид
3

Проверьте manстраницы команд, которые вас интересуют. Эти программы будут указывать, что они читают stdin(попробуйте man grepвоспользоваться популярной командой, которая читает stdin).

thethimble
источник
Я попробовал man grep | grep 'standard input'и получил If no file arguments are specified, the standard input is used.как последний матч. Had Мне пришлось grepнемного попробовать собственный препарат. 😎
ma11hew28
2

Все это опасно для запуска, если в вашей переменной PATH есть каталог, в котором есть пробел, или если имя команды содержит пробел:

rm `which gem`       # Dangerous
rm $(which gem)      # Dangerous
which gem | xargs rm # Dangerous

В GNU Parallel http: // www.gnu.org/software/parallel/ такой проблемы нет, поэтому это будет работать, даже если в вашей переменной PATH есть каталог с пробелом или если имя команды содержит пробел:

which gem | parallel rm
parallel -a <(which bass) rm

Посмотрите вступительное видео для GNU Parallel: http://www.youtube.com/watch?v=OpaiGYxkSuQ

Оле Танге
источник