Скажем, у меня есть следующий конвейер:
cmd1 < input.txt |\
cmd2 |\
cmd4 |\
cmd5 |\
cmd6 |\
(...) |\
cmdN > result.txt
При определенных условиях я хотел бы добавить cmd3
между cmd2
и cmd4
. Есть ли способ создать некий условный конвейер без сохранения результата cmd2 во временный файл? Я хотел бы думать о чем-то вроде:
cmd1 < input.txt |\
cmd2 |\
(${DEFINED}? cmd3 : cat ) |\
cmd4 |\
cmd5 |\
cmd6 |\
(...) |\
cmdN > result.txt
Ответы:
Просто обычные
&&
и||
операторы:(Обратите внимание, что не нужно использовать обратную косую черту, когда линия заканчивается на трубе.)
Обновление в соответствии с наблюдением Джонаса .
Если cmd3 может завершиться с ненулевым кодом выхода и вы не хотите
cat
обрабатывать оставшиеся входные данные, измените логику:источник
cat
возвращается с ненулевым состоянием выхода (обычно при получении SIGPIPE), тоcmd3
будет запущен. Лучше использовать if / then / else, как в ответе Тора, или другие решения, которые избегают выполненияcat
.if
/else
/fi
Работы. Предполагая любую борновую оболочку:источник
Все приведенные ответы замените
cmd3
наcat
. Вы также можете избежать запуска любой команды с помощью:Это POSIX, но обратите внимание, что если в
bash
сценарии,bash
который не находится вsh
-mode (как в сценарии, начинающемся с#! /path/to/bash
), вам необходимо включить расширение псевдонима с помощьюshopt -s expand_aliases
(илиset -o posix
).Другой подход, который по-прежнему не запускает ни одной ненужной команды, заключается в использовании eval:
Или:
В Linux (по крайней мере) вместо
cat
, вы могли бы использовать,pv -q
который используетsplice()
вместоread()
+,write()
чтобы передавать данные между двумя каналами, что позволяет избежать перемещения данных дважды между ядром и пользовательским пространством.источник
В качестве дополнения к принятому ответу manatwork : осознавайте и-false-or gotcha и его взаимодействие с потоками. Например,
выходы
foo
. Не удивительно,а также
оба выхода
baz
. (Обратите внимание, чтоecho foo | grep bar
это ложно и не имеет выхода). Тем не мение,ничего не выводит. Это может или не может быть то, что вы хотите.
источник
else
(Или||
) должны действовать в качестве операции по поддержанию нулевой входной сигнал без изменения. Поэтому заменаcat
наecho
все изменения делает ваш код неактуальным. Относительно «and-false-or gotcha» я не вижу никакого вмешательства в конвейер: pastebin.com/u6Jq0bZe[[ "${DEFINED}" ]] && cmd3 || cat
,cmd3
иcat
не являются взаимоисключающимиthen
иelse
ветви одного и того жеif
, но еслиcmd3
не удастся, тоcat
также будет выполняться. (Конечно, еслиcmd3
всегда удается, или если он потребляет все входные данные, так что не осталось ничего вstdin
течениеcat
процесса, то это не имеет значения.) Если вам нужна какthen
иelse
ветвь, то лучше использовать явнуюif
команду, а не&&
и||
.У меня была похожая ситуация, которую я решил с помощью функций bash :
источник
Вот альтернативное возможное решение:
конкатенация именованных каналов для создания псевдо-конвейера:
источник
Для дальнейшего использования, если вы собираетесь искать условные трубы в рыбе , это то, как вы это делаете:
источник