我正在查看pre-commit hook并发现了以下行,因为我想知道为什么我在提交后总是在我的目录中有一个名为1
的empy文件。
git status 2&>1 > /dev/null
我认为其目的是写下以下内容,并对其进行了更正。
git status 2>&1 > /dev/null
但是,我很好奇以下语法的确切内容,所以我查看了手册页。
git status 2&>1
这是手册页。
Redirecting Standard Output and Standard Error
This construct allows both the standard output (file descriptor 1) and
the standard error output (file descriptor 2) to be redirected to the
file whose name is the expansion of word.
There are two formats for redirecting standard output and standard
error:
&>word
and
>&word
Of the two forms, the first is preferred. This is semantically equiva‐
lent to
>word 2>&1
但是,这个手册页暗示两者是等价的,似乎并非如此。
有人可以澄清手册页并准确解释这种语法会发生什么吗?
答案 0 :(得分:43)
我们在这里使用的运营商是:
>
语法: file_descriptor opt >
file_name >&
语法: file_descriptor opt >&
file_descriptor &>
语法:&>
file_name 如果省略文件描述符,则输入的默认值为0
(stdin),输出的默认值为1
(stdout)。 2
表示stderr。
所以我们有:
>name
表示1>name
- 将stdout重定向到文件name
&>name
表示1>name 2>name
- 将stdout和stderr重定向到文件name
所以当你写git status 2&>1
时,它是git status 2 1>1 2>1
,即
2
实际上作为参数传递给git status
。1
的文件(不是文件描述符1)1
此命令实际上应该创建一个名为1
的文件,其内容是git status 2
的结果 - 即名为2
的文件的状态,可能是"您的分支是最新的,没有提交,工作目录清理",假设您实际上没有跟踪名为2
的文件。
答案 1 :(得分:7)
&>word
(以及>&word
将stdout
和stderr
重定向到扩展单词的结果。在上述情况下,文件为1
2>&1
将stderr
(fd 2)重定向到当前值stdout
(fd 1)。 (在行之后重定向stdout
之前执行此不会达到您的预期效果,并且会将输出拆分而不是将它们组合在一起,这是一个非常常见的shell脚本错误。 >word 2>&1
将两个fds组合成一个发送到同一位置的文件。)
$ { echo stdout; echo stderr >&2; }
stdout
stderr
$ { echo stdout; echo stderr >&2; } >/dev/null
stderr
$ { echo stdout; echo stderr >&2; } >/dev/null 2>&1
$
{ echo stdout; echo stderr >&2; } 2>&1 >/dev/null
stderr
不是那些,虽然看起来相似,但不是一回事。
事实上, git status 2&>1 > /dev/null
实际上正在运行git status 2
,并将&>1
(stdout
和stderr
重定向到文件1
)。几乎肯定不是故意的。你的修正几乎肯定是预期的。
$ git init repro
Initialized empty Git repository in /tmp/repro/.git/
$ cd repro/
$ git status
# On branch master
#
# Initial commit
#
nothing to commit
$ ls
$ git status 2>&1
# On branch master
#
# Initial commit
#
nothing to commit
$ ls
$ git status 2&>1
$ ls
1
$ cat 1
# On branch master
#
# Initial commit
#
nothing to commit