Как наверняка знают многие из нас, всегда полезно, чтобы ваша программа принимала ввод stdin. Очень многие программы допускают такую среду * nix. Это позволяет нам делать классные вещи, такие как трубопровод echo "foo" | less
, Довольно часто можно обнаружить, что cat barfile | baz
логически эквивалентно baz barfile
как за кулисами это просто чтение строк в любом случае.
В настоящее время существует намного больше программ, по которым невозможно передать по умолчанию. У некоторых программ есть флаг, который все еще учитывает поведение, упомянутое выше, но многие не делают.
Теперь мой вопрос: существует ли временный файловый канал?
Теперь, с моей буквально несуществующей способностью писать Bash и около 5 минут в Google, я придумал это
#!/bin/bash
if [ $# -ne 2 ]; then exit 1; fi
f=$(mktemp)
($1) > $f
if [ $? -eq 0 ]; then ($2 $f); else exit $?; fi
rm $f
Называя этот fpipe, мы можем сделать такие вещи, как fpipe 'wget -O- www.example.com' baz
где baz - это программа, в которую мы не можем перейти, но можем baz file
,
Мой вопрос, как мы можем сделать лучше. Я подозреваю, что, обладая большим знанием Bash, переписать приведенный выше скрипт, чтобы принять любое количество аргументов, было бы довольно тривиально (так что мы можем делать такие вещи, как fpipe 'foo x' bar baz
где с помощью трубопровода мы могли бы сделать что-то вроде foo x | bar | baz
, Бах, мы могли бы, вероятно, смешать два и в конечном итоге с такими вещами fpipe 'wget -O- www.example.org | rev' baz
,
Существует ли существующая конструкция, которая достигает этого? Я полагаю, я видел конструкцию своего рода foo x > bar < baz
или что-то в этом роде. Я бы подумал, что это довольно распространенная проблема, но мои поиски ничего не поднимают. Это означает, что я либо недостаточно усердно ищу, либо упускаю что-то довольно очевидное.
Если для достижения этого не существует надлежащего пути (TM), возможно ли определить удобный синтаксис? Сказать, foo x |> baz | rev
где |>
в значительной степени прямо переводится на мой сценарий.
PS: я знаю, что мой / script / очень хрупкий и наивный (например, выход из не-0); не стесняйтесь размещать лучшие.
Ответы:
Это будет работать (в принципе) в любой оболочке, но для этого требуется «достаточно свежая версия» операционной системы:
когда
/dev/stdin
существует, как правило, это символическая ссылка на/proc/self/fd/0
так что если ваша коробка не имеет/dev/stdin
, проверить/proc/self/fd/0
,Конечно изобретение труб был одним из великих нововведений Unix. 1 Временные промежуточные файлы в порядке, но может иметь затраты на производительность, и в случае
у вас может возникнуть проблема с невозможностью размещения файла (весь вывод из первой команды) на диске. Итак, лучшее из обоих миров - использовать именованную трубу. Это позволяет вам захватить стандартный вывод из некоторой программы 2 и предоставить его в качестве входных данных для другой программы в качестве параметра pathname:
Первый
rm -f "$f"
является необходимым так какmktemp
не только генерирует имя файла; он создает файл. Если мы не удалим его,mkfifo
не удастся. (В качестве альтернативы мы могли бы использоватьmktemp -u
, который генерирует имя файла без создания файла.)___________
1 Если Unix «изобрели» трубы несколько спорно. В соответствии с Эволюция системы разделения времени Unix (От Dennis M. Ritchie) (PDF), концепция существовала в других формах в других местах до появления труб в Unix в 1972 году.
2 или вообще любой поток вывода; например, из
cp некий-файл «$ Е»
или жеdd … of="$f"
источник
С достаточно недавней версией Bash:
Это называется процесс замены ,
источник
Вот два метода, чтобы ваш скрипт действовал одинаково, если заданы аргументы файла или если он должен читать строки из stdin:
1) cat файлы, используйте специальное имя файла "-", если в командной строке не указаны файлы
2) если файлы указаны, поместите их содержимое в поток stdin скрипта
источник