带重定向的命令中的空格

Smi*_*ile 7 command-line bash redirect

program 2> error.log 
program &> filename 
program >> filename 2>&1
program 2>&1
Run Code Online (Sandbox Code Playgroud)

我能够弄清楚这些行的含义。

但是我不太明白我应该把空格放在哪里。我也担心放在哪里实际上并不重要。谢谢阅读。

Ser*_*nyy 9

是的,单词和重定向之间的间距无关紧要。这就是简短的回答。

细节在于shell(为简单起见,我们仅参考bash)将某些字符和字符组视为“单词”和“元字符”。从 bash 4.3 手册:

元字符

不加引号时用于分隔单词的字符。以下之一:

|  & ; ( ) < > space tab
Run Code Online (Sandbox Code Playgroud)

字 被外壳视为单个单元的字符序列。也称为令牌。

所以当我们这样做时:

$ echo "hello world">/dev/null
Run Code Online (Sandbox Code Playgroud)

或者

$ echo "hello world" > /dev/null
Run Code Online (Sandbox Code Playgroud)

这仍然是 3 个单词(“hello world”可以被认为是单个 shell 单词,因为它被引用了),带有一个>元字符和几个空格。Shell 会看到它,并首先执行重定向(因此它首先查找元字符),然后根据其标准行为运行命令。

但是,重定向的顺序很重要,尤其是当您使用2>&1. 假设您想将 stderr 和 stdin 都发送到同一位置。这是一个错误的方法:

$ stat ./non-existent file 2>&1  > /dev/null
stat: cannot stat './non-existent': No such file or directory
stat: cannot stat 'file': No such file or directory
Run Code Online (Sandbox Code Playgroud)

您正在将文件描述符2输出到与 相同的位置1,这是您的终端,但它已经这样做了。这就是 stderr 出现的原因。

如果您stdout先重定向,然后才更改2指向的位置 - 那么它会起作用:

$ stat ./non-existent file > /dev/null 2>&1 
Run Code Online (Sandbox Code Playgroud)

  • "echo foo2&gt;bar" 会被解释为 "echo foo 2&gt;bar" 还是 "echo foo2 &gt;bar" (4认同)
  • @PeterGreen 好问题!它将被解释为 `echo foo2 &gt;bar`,因为如果我们使用空格和 `&gt;` 作为元字符将命令拆分为单独的标记,它将是 3 个单词:`echo`、`foo2` 和 `bar`。只有当文件描述符编号单独出现在该行时,才被视为单独的项目,否则它是另一个单词的一部分。 (2认同)