代码之家  ›  专栏  ›  技术社区  ›  Santhosh

linux重定向:在“>somfilename”之前和之后使用“2>&1”的区别

zsh
  •  0
  • Santhosh  · 技术社区  · 6 年前

    有什么区别:

    $ ls > dirlist 2>&1 
    

    $ ls 2>&1 > dirlist
    

    将stderr和stdout重定向到dirlist。

    1 回复  |  直到 6 年前
        1
  •  0
  •   pynexj    6 年前

    对zsh不确定,但根据 Bash manual :

       Note  that  the order of redirections is significant.  For example, the
       command
    
              ls > dirlist 2>&1
    
       directs both standard output and standard error to  the  file  dirlist,
       while the command
    
              ls 2>&1 > dirlist
    
       directs  only the standard output to file dirlist, because the standard
       error was duplicated as standard output before the standard output  was
       redirected to dirlist.
    

    为了 ls > dirlist 2>&1 ,这就是发生的情况(在伪C代码中):

    fd = open("dirlist");
    dup2(fd, 1); // now stdout is a dup of fd so stdout points to "dirlist"
    dup2(1, 2);  // now stderr becomes a dup of stdout so it also points to "dirlist"
    

    为了 ls 2>&1 > dirlist ,这就是发生的情况:

                 // initially, both stdout and stderr point to the tty
    dup2(1, 2);  // now stderr becomes a dup of stdout so they still point to the tty
    
    fd = open("dirlist");
    dup2(fd, 1); // now stdout is a dup of fd so stdout points to "dirlist",
                 // but stderr still points to tty
    
        2
  •  1
  •   Jan Krüger    6 年前

    Shell重定向/管道运算符按其在命令行上出现的顺序应用。一旦你知道了这一点并以正确的方式阅读了操作符,区别就变得很明显了,所以让我们更详细地看一下操作符:

    • FD是file descriptor的缩写,是一个与每个进程上的文件(类似对象)相关联的数字。文件描述符0到2有特殊的含义:它们是标准的输入/输出/错误流。如果在shell中运行的程序没有任何重定向操作符,则它们基本上连接到终端。
    • 重定向 a b 意思是:为 指同一件事 ,即重定向后,两个文件描述符可以互换使用(旧的 丢失)。在内部使用 dup2 系统调用。
    • >foo 取代 stdout 有一个写 foo
    • 2>&1 取代FD 2( stderr )有一个写什么FD 1的句柄( 标准输出 )指 在那一刻 .

    考虑到这一点,下面是这两种变体的情况:

    >foo 2>&1 :shell打开一个新的FD,该FD写入 ,并重定向 标准输出 意思是FD 1现在写入 . 然后,这个FD 1被复制到FD 2中,隐式地关闭旧的fd2(它指的是原始的 标准错误 ). 因此,两个FD都写入 .

    2>&1 >foo :shell首先将FD 1复制到FD 2中,以便将错误写入 标准输出 . 然后,它创建一个新的FD 并复制到FD 1中。由于重定向运算符的顺序,这将覆盖FD 1,但FD 2仍引用“旧”FD 1。因此,FD 2向旧的 标准输出 (可能是你的终端)和FD 1写入 它取代了旧的 标准输出 .