Почему некоторые команды не принимают перенаправление ввода?
Например, echo:
[aesteban@localhost ~]$ cat tmp.txt
Angel
[aesteban@localhost ~]$ echo < tmp.txt
[aesteban@localhost ~]$
Как видите, вывод - просто пустая строка. Согласно моим прочтениям, некоторые команды могут перенаправлять ввод, например, mail:
[aesteban@localhost ~]$ mail barney@example.com < tmp.txt
Таким образом, перенаправление ввода применяется только для интерактивных команд (которые могут ждать ввода)? Как определить, является ли команда интерактивной (кроме попыток)?
3 ответа
Почему некоторые команды не принимают перенаправление ввода?
Короткий ответ: потому что они не были запрограммированы на.
Для программы для чтения из stdin
(это поток, который оболочка подключается к файлу, указанному после <
) не является автоматическим. Это должно быть закодировано программистом. В этом отношении чтение из файлов, указанных в командной строке, также не является автоматическим. Таким образом, содержимое этих файлов, независимо от того, передается ли оно перенаправлением или указывается по имени, волшебным образом не отображается внутри переменных программы без дополнительного кодирования.
Если программа никогда не кодировалась для чтения из потока, не имеет значения, вставили ли вы перенаправление - она просто не будет читать из нее. Согласно спецификации POSIX ( http://pubs.opengroup.org/onlinepubs/009604599/utilities/echo.html), echo
не требуется читать из stdin
и проверяет только аргументы командной строки (и некоторые переменные окружения). Чтобы узнать о других программах, вы можете прочитать исходный код, документацию или просто попробовать, как вы сказали:-)
Чтобы ответить на ваш последний вопрос: вы не можете сказать, что команда является интерактивной. Вы можете определить, подключен ли входной поток, из которого он читает, к терминалу (в отличие, например, от простого файла). Есть примеры на многих языках на http://rosettacode.org/wiki/Check_input_device_is_a_terminal. Вы можете создать почтовую программу, которая использует эту функцию, чтобы определить, используется ли она в интерактивном режиме (принимает команды клавиатуры для чтения почты) или неинтерактивно (скажем, для чтения почтового сообщения из файла). Я не уверен как mail
Является ли. (Обратите внимание, что mail
ведет себя по-разному при вызове с аргументами командной строки или без них!)
Большинство команд, которые читают содержимое файла (или файлов), чьи имена указаны в командной строке, будут считываться из стандартного ввода, если в командной строке не указаны файлы. Некоторые также будут читать из стандартного ввода, если имя файла -
указывается в командной строке; например,
кошка файл 1 - файл 2
будет читать из file1
затем стандартный ввод, а затем file2
, Но если команда обычно не читает содержимое файла (ов), чьи имена указаны в командной строке, то она, вероятно, также ничего не сделает со стандартным вводом. echo
никогда не читает из файлов.
Конечно, есть различные исключения:
-
tr
Команда всегда читает из стандартного ввода и не принимает имя файла (ов) в командной строке. - Если
bc
вызывается с аргументом (ами) имени файла, он читает их, а затем также читает стандартный ввод, если только один из файлов не имеетhalt
или жеquit
команда. - Компиляторы (например, компилятор C, который можно назвать
cc
или жеgcc
), как правило, требуют (или, по крайней мере, сильно предпочитают) имя файла (ов) в командной строке.cc
потерпит неудачу, если вызывается без имен файлов в командной строке.cc -
будет читать стандартный ввод, только если указаны определенные опции. - Не имеет смысла ссылаться
cmp
или жеdiff
с менее чем двумя источниками ввода. Они потерпят неудачу, если вызваны без имен файлов в командной строке. Оба они соблюдают соглашение, что аргумент-
обозначает стандартный ввод.cmp file1
эквивалентноcmp file1 -
; т.е. он будет сравниватьfile1
на стандартный ввод.diff
терпит неудачу, если вызывается с одним аргументом имени файла; вам нужно будет сказатьdiff file1 -
, И пока
dd
примет файл ввода, указанный в командной строке, если он представлен какif=filename
например,dd if=my_iso_file of=/dev/sda1
(
of
или будет), и он будет читать со стандартного ввода, если вы не укажетеif
; например,dd of=/dev/sda1 < my_iso_file
он не принимает аргументы командной строки, которые являются неукрашенными именами файлов (например,
dd my_iso_file > /dev/sda1
а такжеdd my_iso_file of=/dev/sda1
не работают). (Кроме того, в отличие от большинства команд, которые читают из файлов,dd
не будет обрабатывать более одного входного файла из командной строки.)
(Есть, вероятно, другие.)
Прочитайте документацию.
Команда echo не читает из стандартного ввода. Поэтому перенаправление ввода ничего не делает. Руководство Bash гласит:
echo: выводит аргументы, разделенные пробелами, за которыми следует новая строка.
Справочная страница для cat
:
cat - объединяет файлы и печатает на стандартный вывод.