我不明白运行 `cat | 时 `cat` 的行为ls`

我不明白运行 `cat | 时 `cat` 的行为ls`

我知道这是一个无用的命令,但我想了解为什么,无论是在bash或中zsh,当我输入 时cat | lscat都会提示我输入,但只会在一行后返回,而例如</dev/stdin tr -d 'e' | ls会让我输入不同的行,直到我点击Ctrl + D?

答案1

与此仅在 1 秒后打印任何内容的原因相同:

(echo abc; sleep 1; echo def) | tr -d e |cat

标准输出重定向到管道,最多实用程序开始缓冲输出,并且只有在拥有完整的数据块后才在那里写入任何内容。 (块的大小是一个实现细节,可能是几千字节。)您可以使用一些实用程序来禁用缓冲,请参阅:关闭管道中的缓冲

但有些实现cat不做缓冲,而是立即写入。这至少包括 GNU 和 Busybox 实现。 plaincat对缓冲的作用是POSIX 未指定,只有cat -u防止缓冲。

在这里,自从ls没有读到任何内容标准输入因此,管道的完成和退出速度可能比您键入任何内容的速度都要快。因此,当cat/tr开始写入任何内容时,管道已经关闭,写入者收到 SIGPIPE 并退出。由于cat此处立即写入其读取的内容而无需缓冲,因此它会在第一个输入行之后立即获取信号。另一方面,由于tr等待获得完整的缓冲区来写入任何内容,因此第一个输入行不会触发它。如果您输入了足够的数据,tr最终也会将其写入管道,获取信号并退出。

就像你说的,管道 tols是愚蠢的,因为它不读取任何内容。您可以使用类似true或之类的东西false来代替。

答案2

cat不带参数将从 stdin 读取,等待输入第一行当引用交互式设备时,stdin 是行缓冲的,并将其输出到其标准输出,该标准输出被重定向到 的标准输入lsls根本不从标准输入读取,因此它只会将文件列表输出到标准输出并退出。由于ls管道的 -end 被ls(cat的 stdout) 关闭,cat因此也将退出。

对于任何不从 stdin 读取并输出到 stdout 的程序,都可以观察到相同的行为。例如:

cat | uname -a

笔记: </dev/stdin是多余的。它将把标准输入重定向到标准输入。

相关内容