`cat |` 和 `<` 的区别是什么?

3

我希望将filename的内容发送到命令行上的some_cmd。这样做与运行以下命令有何不同:

$ cat filename | some_cmd

并且

$ some_cmd < filename

有没有情况下我可以或应该使用其中一个而不是另一个?

在第一个例子中,您正在创建两个进程,并在它们之间建立一个管道。在第二个例子中,您只运行一个进程,没有管道。在后者中,您可以期望fseek(stdin,...)成功,但在前者中,您应该期望在stdin上寻找失败。 - William Pursell
1
可能是Useless use of cat?的重复问题。 - xhienne
1
@xhienne,如果那里的答案不是受到流行度而非正确性的影响,就好了。 - Charles Duffy
@CharlesDuffy,我不完全同意每个观点,但至少它可能是最好的回答Ashton的问题“有没有情况下我可以使用其中一个而不是另一个?” - xhienne
Ashton,如果这个问题被关闭,请不要感到难过。也不要把它当成个人攻击。重要的是,对于一个给定的问题,读者能够得到一组好的答案。Charles的回答很好,但只提供了一个单一的技术观点(我个人也同意他的观点)。另一方面,如果不链接到其他问题,我们会错过一些同样有趣的答案,我认为值得一读。关闭只会将读者重定向。 - xhienne
显示剩余6条评论
1个回答

8
  • cat foo | somecmd 运行了两个程序——/bin/catsomecmd,并使用一个FIFO将cat的stdout连接到somecmd的stdin上,该FIFO只能从头到尾读取一次。该FIFO也不会显示有关原始文件的元数据,即somecmd无法发现其名称或大小(对于大小而言,除非读取到末尾;这使得对于多GB文件,cat foo | tail变得非常缓慢)。

  • somecmd <foo 只运行了一个程序——somecmd,将其stdin连接到文件foo的直接句柄上。因此,它可以复制该句柄,倒回和重新读取它,将文件的子集分配给不同的线程以并行处理,将文件映射到内存中以进行随机访问等操作。

常见的程序,如GNU sortwc -ctailshuf在获得真正可寻址的文件句柄而不是FIFO时可以更加高效地运行。

始终直接从文件进行重定向,而不要使用cat,除非您有特定且令人信服的理由。


作为这样一个令人信服的理由的示例(您可能需要使用cat),考虑需要流式传输仅可由更高权限用户帐户读取的文件的情况。

sudo -u someuser /bin/cat -- /path/to/somefile | somecmd

...使用 somecmd 以您的原始非特权身份运行,因此可以配置/etc/sudoers仅允许原始命令运行单个特定的cat调用。


很棒的回答。这篇相关的帖子也很值得一读:“$(cat file)”,“$(<file)”和“read … < file”在只有一行的文件中有什么区别? - codeforester

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接