“ cat”和“ cat <”之间的区别


Answers:


106

在第一种情况下,cat打开文件,在第二种情况下,shell打开文件,将其作为cat标准输入传递。

从技术上讲,它们可能会产生不同的效果。例如,可能有一个比该cat程序有更多(或更少)特权的shell实现。对于这种情况,一个可能无法打开文件,而另一个可能。

那不是通常的情况,而是提到要指出的是Shell和cat程序不是同一程序。


83
是的,例如您可以sudo cat myfile.txt。但是,sudo cat < myfile.txt如果您没有读取文件的权限,将无法使用。
zuazo '16

2
请注意,它ksh93具有cat内置功能(除非您/opt/ast/bin处于早期状态,否则默认情况下未启用$PATH)。
斯特凡Chazelas

2
某些程序的行为会有所不同,具体取决于它们是获取文件名参数还是stdin。例如,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)命令的最初目的。请注意,无论如何,shell都会尝试打开作为重定向输入传递的所有文件,但是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]

在标准系统上,shell和cat文件访问权限没有差异,因此两者都将同样成功地失败。正如托马斯·迪基(Thomas Dickey)的回复和所附评论所建议的那样,使用sudo提高cat特权将在行为上产生很大的不同。


5
出于好奇,您真的使用ksh自己的意志,如果这样,为什么

1
@cat-这个问题显然是基于无知。自己建造它,看看。
mikeserv '16

2
我想@mikeserv应该是轻率的,不是很粗鲁,但足够公平,我想

2
@猫-我没有想到否则。无知不是可耻的事情,它只是缺乏知识。如果您不理解为什么有人会选择使用ksh93,那么我只能假设这是因为您从未使用过它。所以我建议你这样做。值得一试。当我告诉您时,请相信我,与相比bash,它ksh93是更好的外壳。它外壳,几乎。
mikeserv '16

5
正如@mikeserv在其他地方指出的,cat < file1 > file2其效果与不可读或不存在cat file1 > file2的情况有很大不同file1。(后一种形式将被截断file2;前一种将不会。)
通配符

7

cat myfile.txt读取文件,myfile.txt然后将其打印到标准输出。

cat < myfile.txt这里cat没有打开任何文件,因此-与许多Unix命令一样-从标准输入读取数据,该输入file.txt由外壳程序从那里引导,并打印到标准输出。


6

@Thomas Dickey的回答很棒。

我只想添加一些有关读取多个文件的事实(与您的问题无关,但仍然如此):

  • cat <file1 <file2 <file3只会读取文件3,至少在bash中。(实际上,这取决于shell,但是大多数shell会将每个指定的文件都复制到stdin中,这会导致最后一个生效。)
  • cat file1 file2 file3会顺序读取所有指定的文件(实际上catconcatenate的缩写形式)。
  • cat file1 file2 file3 <file4 <file5 <file6 只会读取file1,file2,file3(因为在传递文件名参数时,cat会忽略stdin)。
    • cat file1 file2 - file3 <file4 <file5 <file6 将读取file1,file2,file6,file3(因为连字符强制cat不要忽略stdin)。

关于错误。如果无法打开某些指定为参数的文件(不带<),cat将跳过失败的文件(向stderr输出相关消息),但仍会读取其他文件。如果无法打开至少一个指定为重定向的文件(带有<),则shell甚至不会启动cat(即使对于cat实际不使用的重定向,也会发生这种情况)。在这两种情况下,都会返回错误的退出代码。


1
请注意,在你的第一个例子cat将仍然打开file1file2,同样与file4file5你的第三个例子。它只会显示file3,分别。file6如果这些先前的打开说明成功,则返回内容。
jlliagre

@jlliagre,谢谢,我不知道。Strace显然证明了您的正确性。我更正了案例1和3a的带括号的文本。
sasha

0

我们可以使用另一个命令来注意以下两者之间的区别:

wc –w food2.txt

可能的输出:

6 food2.txt

该命令告诉文件名,因为它知道该文件名(作为参数传递)。

wc –w < food2.txt

可能的输出:

6

标准输入重定向到文件food2.txt而不需要命令知道。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.