这个命令如何合法?"> 文件 1 < 文件 2 猫"

sha*_*qed 67 shell io-redirection

假设file2已经存在,命令

> file1 < file2 cat
Run Code Online (Sandbox Code Playgroud)

似乎是复制的内容file2来file1。

但我无法理解这种结构。

我了解“无”是针对file1(创建或删除其内容)。然后将 的内容file2定向到file1。

为什么是cat后file2?它如何知道cat file2操作数的顺序是否不正确?

Kus*_*nda 127

在 shellcat在命令行上执行命令之前,它会处理任何重定向。重定向包括使用<(stdin, read-only), <>(stdin, read+write), >(stdout, write-only) 和>>(stdout, write-only, appending output)重定向输入或输出,还包括<<word(here-documents) 和<<<'...'(在某些 shell 中,“here-strings”)。这些重定向运算符应该不加引号地出现以具有重定向输入或输出的效果,您可以在前面添加一个数字来指定要重定向的文件描述符而不是默认值(stdin (0) 或 stdout (1),具体取决于运算符)。

您显示的命令中有两个重定向:

  1. >file1 这将使命令的标准输出转到file1.
  2. <file2 这将使命令的标准输入来自file2.

这些重定向被放置在命令行上的一个不稳定位置的事实并不重要。

$ cat <file2 >file1
Run Code Online (Sandbox Code Playgroud)

是相同的

$ <file2 cat >file1
Run Code Online (Sandbox Code Playgroud)

这与

$ <file2 >file1 cat
Run Code Online (Sandbox Code Playgroud)

等¹

请注意,cat所有这些实例中的实用程序都是在没有任何命令行参数的情况下执行的。重定向不是cat命令的操作数,它们是 shell 的指令,用于设置进出命令的重定向(将其标准输入和输出连接到文件)。shell在调用命令之前设置重定向。

cat file和cat <file(或者,如果你愿意,<file cat)之间的区别在于,在第一种情况下,cat实用程序本身正在打开文件,该文件在命令行上作为操作数给出,用于读取,而在第二种情况下,外壳程序将打开文件并将cat的输入流连接到它²。在第二种情况下,cat会注意到它没有得到文件操作数,并且会自动切换到从其标准输入读取。这是cat和其他一些实用程序的一个特性,而不是所有实用程序都具有的特性。

cat如果给定了操作数,也会从其标准输入中读取-。同样,这仅适用于cat其他一些实用程序(即shell没有做的任何事情)。要cat在当前目录中名称为 的文件上使用-,请添加文件名的路径,例如./-.

¹在某些情况下,重定向的顺序仍然很重要;随着cat <file2 >file1,例如,file1将不被截断,如果file2无法访问(该重定向被解析从左至右)。cat然而,这个词的相对位置仍然是任意的,不会影响到这一点。

²另见问题“https://unix.stackexchange.com/questions/325706/cat-gives-different-error-when-opening-non-existing-file/”。


shell 在甚至在命令行上执行命令之前设置重定向的事实是这些失败的原因,您最终会得到一个空的输出文件:

$ sort file >file
Run Code Online (Sandbox Code Playgroud)

在这里,shell 将file在执行sort file和连接sort的标准输出到文件之前截断(清空)文件。sort然后该实用程序将打开file并对其内容进行排序(这没什么)。结果(无)通过标准输出流传递到file.

在这种特殊情况下的补救措施(用于“就地”对文件进行排序)是

$ sort -o file file
Run Code Online (Sandbox Code Playgroud)

或者

$ sort file >file.sorted && mv file.sorted file
Run Code Online (Sandbox Code Playgroud)

或者,为了确保原始文件不被删除(以保留某些文件元数据),

$ cp file file.unsorted && sort file.unsorted >file && rm -f file.unsorted
Run Code Online (Sandbox Code Playgroud)

这或多或少是sort使用-o文件指定输出文件名时的作用。


只是为了支持重定向可能位于命令行上实用程序的实际名称之前的声明(我的重点):

“简单命令”是一系列可选的变量赋值和重定向,以任何顺序,可选地后跟单词和重定向,由控制运算符终止。[参考:POSIX Shell 命令语言 2.9.1 简单命令]

还有关于重定向不是实用程序操作数的一部分:

可选编号、重定向运算符和单词不应出现在提供给要执行的命令(如果有)的参数中。[参考:POSIX Shell 命令语言 2.7 重定向]

  • @Steve 移动重定向的自由可用于使某些命令更清晰,例如开头带有输入重定向的管道 `&lt;in foo | bar &gt;out` 将所有内容按逻辑顺序排列。我也很喜欢 shell 脚本的错误输出,如果`echo &gt;&amp;2 发生了不好的事情`。但是 `&gt;out &lt;in cat` 只是混淆 (14认同)
  • 需要注意的一点:当使用 HTML 片段链接到 POSIX 时,最好指定确切的版本(如 http://pubs.opengroup.org/onlinepubs/9699919799.2016edition),因为已知片段在相同版本之间会发生变化规范的修订版(包括我的在内的本网站上的许多答案链接现在都是错误的,因为在 2016 版发布后,这些片段指向了错误的位置)。 (3认同)