Shell重定向i/o命令

ego*_*or7 17 bash shell stdout stderr io-redirection

我正在玩i/o shell重定向.我试过的命令(在bash中):

ls -al *.xyz 2>&1 1> files.lst
Run Code Online (Sandbox Code Playgroud)

ls -al *.xyz 1> files.lst 2>&1
Run Code Online (Sandbox Code Playgroud)

*.xyz当前文件夹中没有任何文件.

这些命令给了我不同的结果.第一个命令ls: *.xyz: No such file or directory在屏幕上显示错误消息.但第二个将此错误消息打印到该文件.为什么第一个命令无法将错误的输出写入文件?

leg*_*s2k 32

猛砸手册有一个明显的例子(类似于你),以显示该订单事宜,也解释了区别.这是摘录的相关部分(强调我的):

请注意,重定向的顺序非常重要.例如,命令

ls> dirlist 2>&1

指示标准输出(文件描述符1)和标准误差(文件描述符2)到文件dirlist,而命令

ls 2>&1> dirlist

仅将标准输出指向文件dirlist,因为在将标准输出重定向到dirlist之前,标准错误是标准输出的副本.

这篇文章从POSIX的角度解释了它.

由于关键差异而发生混淆.>重定向不是通过使左操作数(stderr)指向右操作数(stdout),而是通过制作右操作数的副本并将其分配给左侧.从概念上讲,通过复制而不是通过引用进行分配.

因此,从左到右阅读这是Bash解释的方式:ls > dirlist 2>&1意味着重定向stdout到文件dirlist,然后重定向stderrstdout当前的任何内容(已经是文件dirlist).但是,ls 2>&1 > dirlist会重定向stderrstdout当前的任何内容(即屏幕/终端),然后重定向stdoutdirlist.


mkl*_*nt0 17

重定向是:

  • 从左到右处理.
  • 迭代解释:
    • 一个较早的重定向可能会影响以后之一:
      • 如果较早的重定向已重定向给定的流(由文件描述符编号标识,例如1stdout(默认值)和2stderr),则稍后针对该流的重定向将引用已经重定向的版本.
    • 反之亦然 - 后来的重定向对早期重定向的目标没有追溯效果:
      • 例如,如果您1在早期重定向中指定文件描述符作为目标,那么即使稍后重定向,也会锁定当时的1含义.1
  • 但请注意,在所有重定向到位之前,实际上并不发送输出,并且命令执行开始之前创建或截断任何重定向目标输出文件(这就是您无法读取输出并将输出重定向到的原因单个命令使用相同的文件).

应用于问题的例子:

  • >file 2>&1:

    • >file 首先将stdout(文件描述符1,由不带前缀>的文件描述符编号隐含)重定向到输出文件file
    • 2>&1 然后将stderr(2)重定向到已经重定向的 stdout(1).
    • 净效应是两个原始流最终都进入file.
  • 2>&1 >file:

    • 2>&1首先将stderr重定向到当时原始的标准输出; 由于文件描述符不2参与进一步的重定向,因此stderr输出将转到该点定义的任何stdout - 即原始 stdout,因为这是第一次重定向.
      • 从技术上讲,原始的stdout文件描述符是重复的,并且该重复是stderr随后引用的,这解释了为什么它不受stdout的后续重定向的影响.
    • >file然后将原始标准输出重定向到file- 但这对已经锁定的stderr重定向没有任何影响.
    • 净效果是仅捕获直接发送到stdout的输出file,而发送到stderr输出则输出到(原始的,未重定向的)stdout.


anu*_*ava 12

这个错误:

ls: *.xyz: No such file or directory
Run Code Online (Sandbox Code Playgroud)

stderrls二进制写的.

但是在这个命令中:

ls -al *.xyz 2>&1 1> files.lst
Run Code Online (Sandbox Code Playgroud)

您首先重定向 stderrstdout默认情况下tty(终端)

然后你要重定向stdout到一个文件files.lst,但是请记住,stderr并不重定向到文件,因为你必须stderrstdoutredirection(重定向)之前 stdoutfile重定向.在这种情况下你stderr仍然会被写入tty.

然而,在第二情况下,你改变重定向(第一的顺序stdoutfile,然后stderrstdout),并且正确地重定向stderr到一个file其也正在使用stdout.

  • Stdout默认情况下不是tty.它只是从shell继承而来.如果shell是交互式的并且在tty上运行,那么stdout和stderr默认为tty.如果shell没有在tty上运行,那么它们就不会.我意识到这看起来像是一个尼特,但重要的是不要将stdout与终端混为一谈,人们经常犯这个错误. (11认同)
  • 是的,我的意思是在交互式shell的上下文中,因为OP在交互式shell中运行此命令. (4认同)