Ваш вопрос тесно связан с тем, как используемая оболочка анализирует пользовательский ввод в командной строке.
Если первое слово в командной строке - это программа, расположенная в специальной папке (в основном определяемой как PATH
), и больше не вводятся специальные символы (в зависимости от используемой вами оболочки), все последующие слова, разделенные пробелами или символами табуляции, передаются в программа в специальной форме т.е. массив. С каждым словом в качестве одного элемента в массиве.
То, как программа, которую вы собираетесь вызывать, интерпретирует аргументы (расположенные в массиве), зависит от того, как она запрограммирована. Существует несколько квази-стандартов того, как должен выглядеть синтаксис аргументов, но в целом программист полностью свободен. Таким образом, первый аргумент может быть интерпретирован как имя файла или то, о чем думал программист во время написания программы.
В случае, если вы добавите специальный символ <
или >
в командную строку, оболочка не добавит <
и >
ни последующие слова в массив, который будет передан программе. При наличии <
или >
задании оболочка начинает делать причудливые вещи, поддерживаемые базовым ядром (ключевое слово piping ). Чтобы понять, что происходит, вы должны понимать, что STDIN
и STDOUT
(поскольку это не связано непосредственно, я опускаю STDERR
).
Все, что вы видите на своем терминале (в большинстве случаев это часть вашего дисплея), либо написано оболочкой, либо любой другой программой, которую вы ранее вызывали, в специальный файл (в unix все является файлом ). Этот файл имеет специальный идентификатор и называется STDOUT
. Если программа хочет считывать данные с клавиатуры, она не запрашивает клавиатуру напрямую (по крайней мере, в большинстве случаев), а читает из специального файла с именем STDIN
. Внутренне этот файл подключен к вашему стандартному устройству ввода, в большинстве случаев к вашей клавиатуре.
Если оболочка читает <
или >
в разобранной командной строке, она манипулирует STDIN
или STDOUT
в определенном виде во время выполнения соответствующей программы. STDIN
и больше не STDOUT
указывает на терминал или стандартное устройство ввода, а на последующее имя файла в командной строке.
В случае двух линий
cat file_name
cat < file_name
наблюдаемое поведение идентично, потому что соответствующий разработчик заставляет cat
либо читать данные, STDIN
либо читать данные из файла, чье имя задается в качестве первого аргумента командной строки (который является первым элементом в массиве, в который оболочка передает cat
). Впоследствии cat
записывает весь контент file_name
или STDIN
в терминал, так как мы не инструктируем оболочку манипулировать STDOUT
. Помните, что во второй строке ваша оболочка манипулирует STDIN
таким образом, что она больше не указывает на ваше стандартное устройство ввода, а указывает на файл, называемый file_name
в вашем текущем рабочем каталоге.
В другом случае линии
man < file_name
man
не предназначен для чтения чего-либо, STDIN
если он вызывается без аргумента, т.е. с пустым массивом. Итак, линия
man < file_name
равно
man
Например, man
будет читать что-то из STDIN
тоже, если вы переходите -l -
к man
. С помощью этой опции, заданной в командной строке, вы можете отображать содержимое всего, что man
считывается с STDIN
вашего терминала. Так
man -l - < file_name
будет также работать (но будьте осторожны, man
это не только пейджер, но и анализирует входные данные файла, поэтому содержимое файла и отображаемое содержимое могут отличаться).
Так как STDIN
, STDOUT
и аргументы командной строки интерпретируются все до соответствующего разработчика.
Я надеюсь, что мой ответ может прояснить ситуацию.
man -l - < file_name
для созданияman
интерпретаций вSTDIN
качестве аргументов, но в моей системе это неSTDERR
man -l - < tee man: invalid option -- l man, version 1.6c