在shell中,“2>&1”是什么意思?

在Unix shell中,如果我想将stderrstdout组合到stdout流中以供进一步操作,我可以在命令的末尾添加以下内容:

2>&1

所以,如果我想使用g++的输出head ,我可以这样做:

g++ lots_of_errors 2>&1 | head

所以我只能看到前几个错误。

我总是无法记住这一点,而且我经常不得不去查看它,主要是因为我没有完全理解这个特殊技巧的语法。

有人可以分解这个并且逐字解释什么2>&1是什么意思?


文件描述符1是标准输出( stdout )。
文件描述符2是标准错误( stderr )。

这里有一种方法来记住这个构造(尽管它不完全准确):首先, 2>1可能看起来是将stderr重定向到stdout一种好方法。 但是,它实际上会被解释为“将stderr重定向到名为1的文件”。 &表示接下来是文件描述符而不是文件名。 所以构造变成: 2>&1


echo test > afile.txt

将stdout afile.txtafile.txt 。 这和做..一样。

echo test 1> afile.txt

要重定向stderr,你需要..

echo test 2> afile.txt

>&是将流重定向到另一个文件描述符的语法 - 0是stdin。 1是stdout。 2是stderr。

您可以通过执行将stdout重定向到stderr。

echo test 1>&2 # or echo test >&2

..或相反亦然:

echo test 2>&1

所以,总之.. 2>将stderr重定向到一个(未指定的)文件,追加&1将stderr重定向到stdout


关于重定向的一些技巧

关于这个的一些语法特性可能具有重要的行为。 有一些关于重定向, STDERRSTDOUT和参数排序的小样本。

1 - 覆盖或附加?

符号>意味着重定向。

  • >表示将整个完整文件发送,覆盖目标(如果存在)(请参阅#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
    <-- drwxrwxrwt 118 root root 196608 Jan  7 12:02 /tmp --->
    
    $ ls -ld /tmp /tnt 2>&1 | sed 's/^.*$/<-- & --->/'
    <-- ls: cannot access /tnt: No such file or directory --->
    <-- drwxrwxrwt 118 root root 196608 Jan  7 12:02 /tmp --->
    
    $ 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: cannot access /tnt: No such file or directory --->
    

    请注意,本段中的最后一条命令行与之前的paraghaph中的命令行完全相同,在这里我写的看起来并不是预期的行为(因此,这甚至可能是预期的行为)。

    那么有一些关于重定向的技巧,用于在两个输出上执行不同的操作

    $ ( 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 <(ls -ld /tmp /tnt 2> >(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控制台中;-)

    链接地址: http://www.djcxy.com/p/47263.html

    上一篇: In the shell, what does " 2>&1 " mean?

    下一篇: Extending Git functionality