избегать множественных труб, поврежденных из-за отсутствия команды

В сценариях оболочки я часто использую несколько таких каналов:

cmd1 | cmd2 | cmd3 

Теперь, если cmd2 отсутствует, труба приведет к «сломанной», а cmd3 не получит никакого ввода.

В качестве обходного пути я мог бы явно проверить, существует ли cmd2, но для этого требуется некоторая репликация кода, которую я бы хотел избежать.

Вместо этого я хотел бы получить более краткий тест:

 cmd1 | cmd2; [ $? -eq 127 ] && cat | cmd3 

    2 Solutions collect form web for “избегать множественных труб, поврежденных из-за отсутствия команды”

    На основе вашего примера похоже, что вы ищете способ группировки аргументов для операций с более низким приоритетом, чем | , (т. е. && и || ).

    Таким образом, для группировки можно использовать метасимволы { и } .

    Ваш пример выше можно написать так (используя статус выхода, чтобы определить, существует ли cmd2 или нет).

     cmd1 | { which cmd2 >/dev/null && cmd2 || cat; } | cmd3 

    Например

     printf "hi\n" | { : && rev || cat; } | cat 

    Будет печатать ih

    Ваше предложение использовать подоболочку также будет работать, но без необходимости использовать другой процесс

     printf "hi\n" | ( : && rev || cat ) | cat 

    Я бы сказал, что это, вероятно, менее сложно и лучше для ремонтопригодности, если вы используете явное, if вне трубы.

     if [ which cmd2 >/dev/null ] then cmd1 | cmd3 else cmd1 | cmd2 | cmd3 fi 

    Вы можете написать мини-функцию, чтобы сделать ее более кратким:

     ifexists(){ if command -v "$1" then "$@" else echo "doing cat for missing $1" >&2 cat fi } echo hi | ifexists mycommand | cat -n 
    Linux и Unix - лучшая ОС в мире.