假设file2
已经存在,则命令
> file1 < file2 cat
似乎正在将内容复制file2
到file1
。
但我无法理解这个结构。
我了解“无”的目的是file1
(创建或删除其内容)。然后 的内容file2
将被定向到file1
。
为什么是cat
之后file2
?它如何知道cat file2
操作数的顺序是否不正确?
答案1
shellcat
在命令行上执行命令之前,它会处理所有重定向。重定向包括使用<
(stdin,只读),<>
(stdin,读+写),>
(stdout,只写)和>>
(stdout,只写,附加输出)重定向输入或输出,还包括<<word
(here-documents)和<<<'...'
(在某些 shell 中,“here-strings”)。这些重定向运算符应不加引号,以具有重定向输入或输出的效果,并且您可以在前面添加一个数字来指定要重定向的文件描述符,而不是默认值(stdin (0) 或 stdout (1),具体取决于运算符)。
您显示的命令中有两个重定向:
>file1
这将使命令的标准输出转到file1
.<file2
这将使命令的标准输入来自file2
.
事实上,这些重定向被放置在命令行上一个不稳定的位置并不重要。
$ cat <file2 >file1
是相同的
$ <file2 cat >file1
这与以下相同
$ <file2 >file1 cat
等等 ¹
请注意,cat
所有这些实例中的实用程序都会执行没有任何命令行参数。重定向不是cat
命令的操作数,它们是 shell 的指令,用于设置进出命令的重定向(将其标准输入和输出连接到文件)。 shell 设置重定向前调用命令。
cat file
和cat <file
(或者,如果您愿意的话, )之间的区别<file cat
在于,在第一种情况下,cat
实用程序本身打开文件(该文件在命令行上作为操作数给出)以进行读取,而在第二种情况下,实用程序本身将打开文件以进行读取。壳将打开文件并将cat
的输入流连接到它²。在第二种情况下,cat
会注意到它没有给出文件操作数,并且会自动切换到从其标准输入读取。这是cat
以及其他一些实用程序的一个功能,并非所有实用程序都具有此功能。
cat
如果给定了操作数,也会从其标准输入中读取-
。再次强调,这仅对cat
某些其他实用程序而言是特殊的(即没有什么是特殊的)壳做)。用于cat
当前目录中其名称的文件是 -
,添加文件名路径,例如./-
.
1在某些情况下,重定向的顺序仍然很重要;例如cat <file2 >file1
,file1
如果无法访问,则不会被截断file2
(重定向从左到右解析)。然而,该词的相对位置cat
仍然是任意的,不会影响这一点。
²另见问题cat 在打开不存在的文件时给出不同的错误。
事实上,shell 在命令行上执行命令之前就设置了重定向,这就是为什么此类操作会失败并且最终得到一个空的输出文件的原因:
$ sort file >file
在这里,shell 将file
在执行sort file
并将 的标准输出连接sort
到文件之前截断(清空)文件。然后该sort
实用程序将打开file
并排序其内容(什么也没有)。结果(无)通过标准输出流传递到file
.
在这种特殊情况下(用于“就地”对文件进行排序)的补救措施是
$ sort -o file file
或者
$ sort file >file.sorted && mv file.sorted file
或者,为了确保原始文件不被删除(以保留某些文件元数据),
$ cp file file.unsorted && sort file.unsorted >file && rm -f file.unsorted
这或多或少是sort
使用-o
文件指定输出文件名时的作用。
只是为了支持重定向可能位于命令行上实用程序的实际名称之前的声明(我的重点):
“简单命令”是一系列可选的变量分配和重定向,以任何顺序,可选地后跟单词和重定向,由控制运算符终止。[参考:POSIX Shell 命令语言 2.9.1 简单命令]
还有关于重定向不属于实用程序操作数的一部分:
可选数字、重定向运算符和单词不得出现在提供给要执行的命令的参数中(如果有)。[参考:POSIX Shell 命令语言 2.7 重定向]