为什么小于号不能代替 bash 中的 cat ?

bug*_*bug 19 shell bash io-redirection cat

我听说过“无用的使用 cat”并找到了一些建议,但以下内容在我的 bash shell 中没有任何输出。

< filename
Run Code Online (Sandbox Code Playgroud)

不过,使用 cat 可以按预期工作。

cat filename
Run Code Online (Sandbox Code Playgroud)

我使用的是 Fedora Core 18 和 GNU bash,版本 4.2.45(1)。

编辑:在管道前使用它也不起作用。

< filename | grep pattern
Run Code Online (Sandbox Code Playgroud)

而使用 cat 可以按预期工作。

cat filename | grep pattern
Run Code Online (Sandbox Code Playgroud)

EDIT2:澄清一下,我知道我可以使用这个

grep pattern < filename
Run Code Online (Sandbox Code Playgroud)

但我在这里读到/sf/ask/819738671/我也可以在命令前使用它。但它在命令前不起作用。

slm*_*slm 28

小于和符号 ( <) 正在打开文件并将其附加到某些应用程序/程序的标准输入设备句柄。但是你没有给 shell 任何应用程序来附加输入。

例子

这两个示例基本上做相同的事情,但以两种略有不同的方式获取输入。

打开文件

$ cat blah.txt 
hi
Run Code Online (Sandbox Code Playgroud)

打开标准输入

$ cat < blah.txt 
hi
Run Code Online (Sandbox Code Playgroud)

从窗帘后面偷看

您可以使用它strace来查看发生了什么。

当我们从文件中读取时

open("blah.txt", O_RDONLY)              = 3
fstat(3, {st_mode=S_IFREG|0664, st_size=3, ...}) = 0
fadvise64(3, 0, 0, POSIX_FADV_SEQUENTIAL) = 0
read(3, "hi\n", 65536)                  = 3
write(1, "hi\n", 3hi
)                     = 3
read(3, "", 65536)                      = 0
close(3)                                = 0
close(1)                                = 0
Run Code Online (Sandbox Code Playgroud)

当我们从 STDIN 读取时(标识为 0)

read(0, "hi\n", 65536)                  = 3
write(1, "hi\n", 3hi
)                     = 3
read(0, "", 65536)                      = 0
close(0)                                = 0
close(1)                                = 0
Run Code Online (Sandbox Code Playgroud)

在第一个示例中,我们可以看到cat打开了文件并从中读取了blah.txt. 在第二个中我们可以看到通过 STDIN 文件描述符cat读取文件的内容,blah.txt描述符编号为 0。

read(0, "hi\n", 65536)                  = 3
Run Code Online (Sandbox Code Playgroud)


ter*_*don 16

经典无用的用法cat是当您使用它为完全能够直接打开文件的程序提供输入时。例如:

坏的

cat file | grep foo
cat file | while read line; do echo "$line"; done
cat file | sed 's/a/b/'
cat file | awk '{print $1}'
Run Code Online (Sandbox Code Playgroud)

好的

grep foo file
while read line; do echo "$line"; done < file 
sed 's/a/b/' file
awk '{print $1}' file
Run Code Online (Sandbox Code Playgroud)

也不错(<file可以在命令的任一侧)

<file grep foo
 sed 's/a/b/' < file
<file awk '{print $1}' 
Run Code Online (Sandbox Code Playgroud)

  • “坏”在这里是主观的。我发现它们总体上更好,因为它_way_更一致且更易于阅读。并且数据流完全从左到右,如果涉及更多管道就应该如此 (7认同)
  • @Izkata 他们是“坏的”,因为它们是 `cat` 的无用用法。 (2认同)

Sté*_*las 14

UUOC 位于:

cat somefile | some-cmd
Run Code Online (Sandbox Code Playgroud)

或者

cat < somefile | some-cmd
Run Code Online (Sandbox Code Playgroud)

在那里,some-cmd正在somefile从一个管道中读取 的内容,该管道cat本身从somefile.

some-cmd可以直接读取somefile(在 shell 在标准输入上打开它之后),不需要cat

some-cmd < somefile
Run Code Online (Sandbox Code Playgroud)

或者

< somefile some-cmd
Run Code Online (Sandbox Code Playgroud)

(重定向可以出现在简单命令行上的任何位置)。