Почему некоторые команды не принимают перенаправление ввода?

Например, 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 - объединяет файлы и печатает на стандартный вывод.

Другие вопросы по тегам