Разница между «кошкой» и «кошкой <»

70

Я работал над учебником и видел, как cat myfile.txtи то и другое cat < myfile.txt. Есть ли разница между этими двумя последовательностями команд? Кажется, оба печатают содержимое файла в оболочку.

новобранец
источник

Ответы:

106

В первом случае catоткрывается файл, а во втором случае оболочка открывает файл, передавая его в качестве catстандартного ввода.

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

Это не обычный сценарий, но упоминается, чтобы указать, что оболочка и catне одна и та же программа.

Томас Дики
источник
83
Да, и, например, вы можете сделать sudo cat myfile.txt. Но sudo cat < myfile.txtне будет работать, если у вас нет прав на чтение файла.
zuazo
2
Обратите внимание , что ksh93имеет catвстроенные (не включена по умолчанию , если вы не имеете /opt/ast/binв начале вашего , $PATHхотя).
Стефан Шазелас
2
Некоторые программы ведут себя по-разному в зависимости от того, получают ли они аргумент имени файла или стандартный ввод. Например, wcнапечатает имя файла до подсчета, когда передается аргумент.
Бармар
21

В вашем тестовом примере нет существенных видимых различий. Наиболее очевидным будет сообщение об ошибке, которое вы получите, если myfile.txtв текущем каталоге нет имени файла или если вам не разрешено его читать.

В первом случае, catбудет жаловаться, а во втором случае ваша оболочка, четко показывая, какой процесс пытается открыть файл, catв первом и оболочку во втором.

$ cat myfile.txt
cat: myfile.txt: No such file or directory
$ cat < myfile.txt
ksh93: myfile.txt: cannot open [No such file or directory]

В более общем случае основным отличием является использование перенаправлений, которые нельзя использовать для печати содержимого более чем одного файла, что, в конце концов, является первоначальной целью команды cat(т.е. cat enate). Обратите внимание, что оболочка в любом случае попытается открыть все файлы, переданные в качестве перенаправленного ввода, но только фактически передаст последний из них, catесли вы не используете zshи его multios"zshism".

$ echo one > one
$ echo two > two
$ cat one two # cat opens one, shows one, opens two, shows two
one
two
$ cat < one < two # sh opens one then opens two, cat shows stdin (two)
two
$ rm one two
$ echo one > one
$ cat one two # cat opens and shows one, fails to open two
one
cat: two: No such file or directory
$ cat < one < two # the shell opens one then opens two, fails and 
                  # displays an error message, cat gets nothing on stdin
                  # so shows nothing
ksh93: two: cannot open [No such file or directory]

В стандартной системе оболочки и не catимеют различий в правах доступа к файлам, поэтому оба будут одинаково успешны. Использование sudoдля повышения catпривилегий будет иметь большое значение в поведении, как уже предлагал Томас Дики и прикрепленные комментарии.

jlliagre
источник
5
Из любопытства, вы действительно используете kshсвою волю, и если да, то почему ?
кот
1
@cat - этот вопрос явно основан на невежестве. Построй сам и посмотри.
mikeserv
2
@mikeserv, который должен был быть легкомысленным, не слишком грубым, но, по-моему, достаточно справедливым
кошка
2
@ Cat - я не предполагал иначе. невежество - это не то, за что стыдиться, это лишь недостаток знаний. Если вы не понимаете, почему кто-то может использовать ksh93, тогда я могу только предположить, что вы его никогда не использовали. так что я рекомендую вам сделать. безусловно, стоит попробовать. и поверь мне, когда я скажу тебе, что, по сравнению с этим bash, ksh93это лучшая оболочка. это почти что оболочка.
mikeserv
5
Как указал @mikeserv в другом месте , cat < file1 > file2эффект сильно отличается от cat file1 > file2случая, когда file1он не читается или отсутствует. (Последняя форма усекается file2; первая не будет.)
Wildcard
7

cat myfile.txtчитает файл, myfile.txtзатем печатает его на стандартный вывод.

cat < myfile.txtздесь catне дано никаких файлов для открытия, поэтому, как и многие команды Unix, считывает данные из стандартного ввода, который направляется туда из file.txtоболочки, и печатает в стандартный вывод.

Хамза Аббад
источник
6

Ответ @Thomas Dickey блестящий.

Я просто хочу добавить некоторые очевидные факты о случае чтения нескольких файлов (слабо связанных с вашим вопросом, но все же):

  • cat <file1 <file2 <file3будет читать только file3, по крайней мере, в bash. (На самом деле, это зависит от оболочки, но большинство оболочек будет дублировать каждый указанный файл в стандартный ввод, что приведет к последнему эффекту.)
  • cat file1 file2 file3будет читать все указанные файлы последовательно (на самом деле cat - сокращенная форма слова concatenate ).
  • cat file1 file2 file3 <file4 <file5 <file6 будет читать только file1, file2, file3 (поскольку cat игнорирует стандартный ввод, когда передаются аргументы имени файла).
    • cat file1 file2 - file3 <file4 <file5 <file6 будет читать file1, file2, file6, file3 (поскольку дефис заставляет cat не игнорировать стандартный ввод).

И про ошибки. В случае невозможности открыть некоторые из файлов, указанных в качестве аргументов (без <), cat пропустит сбойные файлы (с выводом соответствующего сообщения в stderr), но все равно прочитает другие файлы. В случае невозможности открыть хотя бы один из файлов, указанных как перенаправления (с помощью <), оболочка даже не запустит cat (это происходит даже для тех перенаправлений, которые фактически не используются cat). В обоих случаях будет возвращен ошибочный код выхода.

саша
источник
1
Обратите внимание, что в вашем первом примере cat, тем не менее, откроется file1и file2, так же, как file4и file5в вашем третьем примере. Это только покажет file3, соотв. file6содержимое, если эти предыдущие открытые инструкции завершаются успешно.
Jlliagre
@jlliagre, спасибо, я этого не знал. Стрейс явно доказал вашу правоту. Я исправил текст в скобках для случаев 1 и 3a.
Саша
0

мы можем использовать другую команду, чтобы заметить разницу между:

wc –w food2.txt ,

Возможный вывод:

6 food2.txt ,

команда сообщает имя файла, поскольку оно знает его (передается в качестве аргумента).

wc –w < food2.txt ,

Возможный вывод:

6 ,

стандартный ввод перенаправляется в файл food2.txt, и команда не знает об этом.

user307770
источник