Как стандартный ввод одной программы можно передать как аргумент другой?


17

Допустим, существует программа, которая принимает два аргумента; входной файл и выходной файл.

Что делать, если я не хочу сохранять этот выходной файл на диск, а просто передать его stdinдругой программе. Есть ли способ добиться этого?

Многие команды, с которыми я сталкиваюсь в Linux, предоставляют опцию для передачи «-» в качестве аргумента выходного файла, что делает то, что я указал выше. Это потому, что передача stdinпрограммы в качестве аргумента невозможна? Если это так, как мы это делаем?

Пример того, как я мог бы использовать это изображение:

pdftotext "C BY BRIAN W KERNIGHAN & DENNIS M RITCHIE.pdf" stdin(echo)

Я использую оболочку bash.


1
cat <file | cmd /dev/fd/0работает на большинстве офисов.
mikeserv

Не работает для меня Пробовали с: cat < README.txt | cp /dev/fd/0. cp: missing destination file operand after ‘/dev/fd/0’ Try 'cp --help' for more information.
Там

1
program input-file /dev/stdout | another-program? Также обратите внимание, что echoничего не читает из стандартного ввода.
Яегаси

1
@Dziugas - конечно, нет - вы не можете cpфайл нигде. echo 1 2 3| cp /dev/fd/0 /dev/ttyнапечатает 1 2 3. И, кстати, с /dev/fd/[num]большей вероятностью сработает, чем /dev/std(in|out|err)в большинстве случаев. См. Портативность ссылок файлов-дескрипторов о том, что и где вы можете ожидать.
mikeserv

1
Хорошая UNIX-программа будет записывать в стандартный вывод, предоставляя пользователю право решать, желают ли они перенаправить в файл или передать в другую команду.
Хорхе Букаран

Ответы:


13

Если программа поддерживает запись в любой файловый дескриптор, даже если она не может искать, вы можете использовать /dev/stdoutв качестве выходного файла. Это символическая ссылка /proc/self/fd/1на мою систему. Файловым дескриптором 1 является стандартный вывод.


Это решило мой запрос. Так нет ли способа сделать это, когда программу нужно искать?
Дзюгас

3
Если вы пытаетесь запретить доступ к диску, вы можете записать файл в / dev / shm /, однако, если вам не нужен какой-либо файл в файловой системе, то, насколько я знаю, нет способа искать трубка. Поиск вперед означает, что ему придется буферизовать все в памяти до тех пор, пока он не достигнет этой точки, а поиск назад означает, что все в памяти буферизовано.
TiCPU

pdftotextкак и многие (но не все), другие утилиты также поддерживают -это (что будет работать даже в системах, которые не поддерживают / dev / stdout, или где / dev / stdout не работает, как ожидалось, как в Linux, где stdout не поддерживается). трубка). pdftotext file.pdf - | wc -c
Стефан Шазелас

11

Со pdftotextстраницы руководства :

Если текстовым файлом является «-», текст отправляется на стандартный вывод.

Так что в этом случае все, что вам нужно, это:

pdftotext "C BY BRIAN W KERNIGHAN & DENNIS M RITCHIE.pdf" -

Или, если вы хотите передать это в STDIN другой программы:

pdftotext "C BY BRIAN W KERNIGHAN & DENNIS M RITCHIE.pdf" - | another_prog

Использование в -качестве замены имени файла является соглашением, которому следуют многие утилиты (включая pdftotext), когда мы хотим вводить из STDIN или выводить в STDOUT. Однако не все утилиты следуют этому соглашению. В этом случае идиоматическим способом сделать это в bash является использование подстановки процесса :

my_utility "C BY BRIAN W KERNIGHAN & DENNIS M RITCHIE.pdf" >( cat )

Здесь >( )поведение в значительной степени похоже на файл, переданный my_utility, но вместо того, чтобы быть реальным файлом, поток передается в стандартный поток содержимого процесса, то есть cat. Так что здесь, текст должен в конечном итоге выводиться по мере необходимости.

Использование cat почти всегда вызывает тревогу UUOC на подобных форумах. Я утверждаю, что если утилита не поддерживает -, тогда это полезное использование cat, хотя, если есть какие-либо способы сделать эту замену процесса без cat, тогда я весь слух ;-).

Однако, если (как говорится в вопросе) конечным пунктом назначения потока является STDIN другой программы, то это catможно исключить:

my_utility "C BY BRIAN W KERNIGHAN & DENNIS M RITCHIE.pdf" >( another_prog )

2
И позвольте мне вернуться назад еще раз: если prog2запись в stdout, лучше, чем , потому что форма ожидает завершения (т. Е. До того, как оболочка выдаст следующее приглашение или перейдет к следующей команде (например, после или )), в то время как Без формы форма ожидает только завершения. Кроме того, после формы отображается статус выхода из , тогда как в другой - статус выхода из . (Вы платите деньги и выбираете.)prog1 input_file >( cat ) | prog2prog1 input_file >( prog2 )catprog2;&&catprog1cat$?prog2$?prog1
Скотт,

4

Если ваша оболочка поддерживает их, самым простым способом выполнения таких манипуляций будет использование подстановки процесса : <(…)и >(…). Это работает в bash, zsh и ksh и, возможно, в других оболочках. Например:

$ sort <(printf "b\nc\na\n")
a
b
c
$ ls
foo
$ cp <(find . -name foo) bar
$ ls
bar  foo

Тем не менее, это не поможет в приведенном вами примере, так pdftotextкак сохранит в текстовом файле. Хотя ваш лучший выбор (кроме очевидного использования -) - это использование, /dev/stdoutпредложенное @TiCPU, вы также можете использовать другую функцию оболочки. Конструкция !:Nссылается на N-й аргумент предыдущей команды. Следовательно, вы можете сделать:

$ pdftotext "C BY BRIAN W KERNIGHAN & DENNIS M RITCHIE.pdf"  out.txt
$ cat !:2

1
Хотя я согласен, что это cat <()может быть полезно в некоторых ситуациях, в этом случае, однако, это не работает вообще. Проблема (очень плохо описанная OP, я должен признать) заключается в том, что она pdftotextпринимает два аргумента: входной файл и выходной файл . Если второй аргумент отсутствует, то он ничего не производит, поэтому cat <(pdftotext "file.pdf")также ничего не возвращает. Команду можно обмануть pdftotext, приведя >(cat)в качестве второго аргумента, как ответил Digital Trauma, но cat <()здесь это бессмысленно. Очевидно, в pdftotextслучае, если это лучше всего использовать в -качестве имени выходного файла.
Джимми

1
@ Скотт Как мой ответ UUOC? Как бы вы сделали этот процесс замены без кота? >( )будет эффективно направлять поток к тому процессу, который находится внутри, поэтому нам действительно нужен catздесь для вывода этого потока. Обычно мы должны иметь возможность сделать что-то подобное pdftotext input.pdf -, но, очевидно pdftotext, не поддерживает -параметр для вывода непосредственно в стандартный вывод вместо файла - попробуйте это.
Цифровая травма

1
@DigitalTrauma это не так. Я считаю, что cat - это самая быстрая скорость, которую вы можете получить в случае простой печати, но на самом деле вы можете использовать другую команду, >(grep something)чтобы быть более полезной. Кстати, моя pdftotext 3.04 делать поддержка в -качестве выходного файла, так что я немного удивлен всей дискуссии.
Джимми

1
@terdon Я ненавижу быть сторонником, но это, кажется, не работает. В частности, он не отличается от запуска pdftotext "C BY BRIAN W KERNIGHAN & DENNIS M RITCHIE.pdf", который помещает вывод в вызываемый файл C BY BRIAN W KERNIGHAN & DENNIS M RITCHIE.txt, но ни один из текста не выводится в STDOUT для передачи в другую программу.
Цифровая травма

1
@DigitalTrauma это не является сторонником! Это я идиот. Спасибо за указание на это и, пожалуйста, никогда не приносите извинения, указывая на ошибки. Я бы предпочел, чтобы моя ошибка была указана мне, и я узнал что-то, а не оставил это во всей своей сомнительной славе.
Тердон

-2
cmd tty

ttyвозвращает имя подключенного терминала stdout.


Я не уверен, как это отвечает на вопрос, касающийся объединения команд; возможно, вы расширите пример того, как вы этого добьетесь.
дхаг

Я предполагаю, что вы говорите проверить ttyимя терминала, а затем использовать этот файл, например, в качестве вывода pdftotext file.pdf /dev/pts/2. В таком случае я согласен.
Джимми

Это может быть сокращено / автоматизировано ; который обычно будет эквивалентен . Но этот подход предполагает, что цель состоит в том, чтобы отобразить вывод (т. Е. В терминале), а это не то, что задает вопрос (см. Комментарии к ответу Тердона для некоторого разъяснения значения вопроса). prog1  input_file $(tty)prog1  input_file /dev/ttyprog1
Скотт
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.