在Unix shell中,如果要将stderr和stdout组合到stdout流中以进行进一步的操作,则可以在命令末尾附加以下内容:
2>&1
因此,如果我想在g++的输出中使用head ,则可以执行以下操作:
g++ lots_of_errors 2>&1 | head
因此我只能看到前几个错误。
我总是很难记住这一点,而且我经常不得不去查找它,这主要是因为我不完全理解这个特殊技巧的语法。
有人可以分手并逐个字符地解释2>&1含义吗?
#1楼
人们,永远记住paxdiablo关于重定向目标当前位置的提示……这很重要。
我对2>&1运算符的个人记忆是:
想想&作为意义'and'或'add' (字符是一个ampers - 而且 ,不是吗?)
因此它变成: '将2 (stderr)重定向到已经(当前) 1 (stdout)所在的位置并添加两个流“ 。
同样的助记符也可以用于其他经常使用的重定向, 1>&2 :
考虑&含义, and add ...(您对&符有想法,对吗?)
因此它变成: '将1 (stdout)重定向到2 (stderr)已经/当前所在的位置并添加两个流' 。
并始终记住:您必须从右到左( 而不是从左到右)“从头到尾”读取重定向链。
#2楼
有关重定向的一些技巧
关于此的某些语法特殊性可能具有重要的行为。 关于重定向, STDERR , STDOUT和参数排序有一些小示例。
1-覆盖还是附加?
符号>均值重定向 。
>表示发送到一个完整的完整文件 ,如果存在noclobber覆盖目标(请参阅稍后的#3 noclobber bash功能)。
>>表示除发送外还将附加到目标(如果存在)。
无论如何,如果文件不存在,则会创建该文件。
2- Shell命令行取决于顺序!!
为了测试这一点,我们需要一个简单的命令,该命令将在两个输出上发送一些信息 :
$ ls -ld /tmp /tnt
ls: cannot access /tnt: No such file or directory
drwxrwxrwt 118 root root 196608 Jan 7 11:49 /tmp
$ ls -ld /tmp /tnt >/dev/null
ls: cannot access /tnt: No such file or directory
$ ls -ld /tmp /tnt 2>/dev/null
drwxrwxrwt 118 root root 196608 Jan 7 11:49 /tmp
(当然,希望您没有一个名为/tnt的目录)。 好吧,我们有!!
因此,让我们看看:
$ ls -ld /tmp /tnt >/dev/null
ls: cannot access /tnt: No such file or directory
$ ls -ld /tmp /tnt >/dev/null 2>&1
$ ls -ld /tmp /tnt 2>&1 >/dev/null
ls: cannot access /tnt: No such file or directory
最后一个命令行将STDERR转储到控制台,这似乎不是预期的行为...但是...
如果要对一个输出,另一个输出或两个输出进行后期过滤 :
$ ls -ld /tmp /tnt | sed 's/^.*$//'
ls: cannot access /tnt: No such file or directory
$ ls -ld /tmp /tnt 2>&1 | sed 's/^.*$//'
$ ls -ld /tmp /tnt >/dev/null | sed 's/^.*$//'
ls: cannot access /tnt: No such file or directory
$ ls -ld /tmp /tnt >/dev/null 2>&1 | sed 's/^.*$//'
$ ls -ld /tmp /tnt 2>&1 >/dev/null | sed 's/^.*$//'
请注意,本段的最后一个命令行与上一段完全相同,在那段我写的似乎不是预期的行为 (因此,这甚至可能是预期的行为)。
嗯,关于重定向, 在两个输出上执行不同的操作有一些技巧:
$ ( ls -ld /tmp /tnt | sed 's/^/O: /' >&9 ) 9>&2 2>&1 | sed 's/^/E: /'
O: drwxrwxrwt 118 root root 196608 Jan 7 12:13 /tmp
E: ls: cannot access /tnt: No such file or directory
注意: &9描述符会由于( ) 9>&2自发出现。
附录:nota! 在新版本的bash ( >4.0 )中,有一种新功能和更性感的语法可以执行以下操作:
$ ls -ld /tmp /tnt 2> >(sed 's/^/E: /') > >(sed 's/^/O: /')
O: drwxrwxrwt 17 root root 28672 Nov 5 23:00 /tmp
E: ls: cannot access /tnt: No such file or directory
最后是这样的级联输出格式:
$ ((ls -ld /tmp /tnt |sed 's/^/O: /' >&9 ) 2>&1 |sed 's/^/E: /') 9>&1| cat -n
1 O: drwxrwxrwt 118 root root 196608 Jan 7 12:29 /tmp
2 E: ls: cannot access /tnt: No such file or directory
附录:nota! 两种方式都具有相同的新语法:
$ cat -n >(sed 's/^/E: /') > >(sed 's/^/O: /'))
1 O: drwxrwxrwt 17 root root 28672 Nov 5 23:00 /tmp
2 E: ls: cannot access /tnt: No such file or directory
当STDOUT经过一个特定的过滤器时, STDERR到达另一个过滤器,最后合并的两个输出都经过第三个命令过滤器。
3-关于noclobber选项和>|词汇 句法
那是关于覆盖 :
当set -o noclobber指示bash 不覆盖任何现有文件时, >| 语法使您可以克服此限制:
$ testfile=$(mktemp /tmp/testNoClobberDate-XXXXXX)
$ date > $testfile ; cat $testfile
Mon Jan 7 13:18:15 CET 2013
$ date > $testfile ; cat $testfile
Mon Jan 7 13:18:19 CET 2013
$ date > $testfile ; cat $testfile
Mon Jan 7 13:18:21 CET 2013
现在,文件每次都会被覆盖:
$ set -o noclobber
$ date > $testfile ; cat $testfile
bash: /tmp/testNoClobberDate-WW1xi9: cannot overwrite existing file
Mon Jan 7 13:18:21 CET 2013
$ date > $testfile ; cat $testfile
bash: /tmp/testNoClobberDate-WW1xi9: cannot overwrite existing file
Mon Jan 7 13:18:21 CET 2013
通过>| :
$ date >| $testfile ; cat $testfile
Mon Jan 7 13:18:58 CET 2013
$ date >| $testfile ; cat $testfile
Mon Jan 7 13:19:01 CET 2013
取消设置此选项和/或查询是否已设置。
$ set -o | grep noclobber
noclobber on
$ set +o noclobber
$ set -o | grep noclobber
noclobber off
$ date > $testfile ; cat $testfile
Mon Jan 7 13:24:27 CET 2013
$ rm $testfile
4-最后一招等等
为了重定向给定命令的两个输出,我们看到正确的语法可能是:
$ ls -ld /tmp /tnt >/dev/null 2>&1
对于这种特殊情况,有一个快捷语法: &> ...或>&
$ ls -ld /tmp /tnt &>/dev/null
$ ls -ld /tmp /tnt >&/dev/null
注意:如果2>&1存在,则1>&2也是正确的语法:
$ ls -ld /tmp /tnt 2>/dev/null 1>&2
4b-现在,我将让您考虑:
$ ls -ld /tmp /tnt 2>&1 1>&2 | sed -e s/^/++/
++/bin/ls: cannot access /tnt: No such file or directory
++drwxrwxrwt 193 root root 196608 Feb 9 11:08 /tmp/
$ ls -ld /tmp /tnt 1>&2 2>&1 | sed -e s/^/++/
/bin/ls: cannot access /tnt: No such file or directory
drwxrwxrwt 193 root root 196608 Feb 9 11:08 /tmp/
4c-如果您对更多信息感兴趣
您可以点击以下内容阅读精美的手册:
man -Len -Pless\ +/^REDIRECTION bash
在bash控制台中;-)
#3楼
2是控制台标准错误。
1是控制台标准输出。
这是标准的Unix,Windows也遵循POSIX。
例如,当您跑步时
perl test.pl 2>&1
标准错误将重定向到标准输出,因此您可以同时看到两个输出:
perl test.pl > debug.log 2>&1
执行后,您可以在debug.log中看到所有输出,包括错误。
perl test.pl 1>out.log 2>err.log
然后,标准输出转到out.log,标准错误转到err.log。
我建议您尝试了解这些。
#4楼
这就像将错误传递到标准输出或终端一样。
也就是说, cmd不是命令:
$cmd 2>filename
cat filename
command not found
错误将发送到文件,如下所示:
2>&1
标准错误发送到终端。
#5楼
重定向输入
输入的重定向导致打开其名称由单词扩展产生的文件,以供在文件描述符n上读取;如果未指定n,则打开标准输入(文件描述符0)。
重定向输入的一般格式为:
[n]
重定向输出
输出重定向导致打开其名称由单词扩展产生的文件,以便在文件描述符n上进行写操作;如果未指定n,则打开标准输出(文件描述符1)。 如果文件不存在,则创建该文件; 如果确实存在,则将其截断为零大小。
重定向输出的一般格式为:
[n]>word
移动文件描述符
重定向运算符,
[n]
将文件描述符数字移动到文件描述符n,或者如果未指定n,则将标准输入(文件描述符0)移动到文件描述符n。 数字复制到n后关闭。
同样,重定向运算符
[n]>&digit-
将文件描述符数字移动到文件描述符n,或者如果未指定n,则将标准输出(文件描述符1)移动到文件描述符n。
参考:
man bash
键入/^REDIRECT定位到redirection部分,并了解更多信息...
在线版本在这里:
PS:
很多时候, man是学习Linux的强大工具。