Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/bash/17.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Bash Shell重定向i/o顺序_Bash_Shell_Stdout_Stderr_Io Redirection - Fatal编程技术网

Bash Shell重定向i/o顺序

Bash Shell重定向i/o顺序,bash,shell,stdout,stderr,io-redirection,Bash,Shell,Stdout,Stderr,Io Redirection,我正在玩I/o外壳重定向。我尝试过的命令(在bash中): 及 当前文件夹中没有任何*.xyz文件 这些命令给出了不同的结果。第一个命令显示错误消息ls:*.xyz:屏幕上没有这样的文件或目录。但是第二个会将此错误消息打印到文件中。为什么第一个命令无法将错误输出写入文件?此错误: ls: *.xyz: No such file or directory 正在由ls二进制文件写入stderr 但是,在该命令中: ls -al *.xyz 2>&1 1> files.lst

我正在玩I/o外壳重定向。我尝试过的命令(在bash中):

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

这些命令给出了不同的结果。第一个命令显示错误消息
ls:*.xyz:屏幕上没有这样的文件或目录
。但是第二个会将此错误消息打印到文件中。为什么第一个命令无法将错误输出写入文件?

此错误:

ls: *.xyz: No such file or directory
正在由
ls
二进制文件写入
stderr

但是,在该命令中:

ls -al *.xyz 2>&1 1> files.lst
您首先将
stderr
重定向到
stdout
,默认情况下会转到
tty
(终端)

然后您将
stdout
重定向到一个文件
files.lst
,但是请记住,stderr不会重定向到文件,因为您在
stdout
重定向之前有
stdout
重定向到
file
。在这种情况下,您的
stderr
仍然会写入
tty

但是,在第二种情况下,您更改重定向顺序(首先将
stdout
更改为
file
,然后将
stderr
更改为
stdout
),这样可以正确地将
stderr
重定向到
文件,而
stdout
也在使用该文件,因为顺序确实很重要。 在第一种情况下,首先将stderr(2)重定向到stdout(1)。 然后将(1)重定向到一个文件。但是stderr(2)仍然指向运行该命令的shell的stdout。在这种情况下,将(1)指向一个文件不会改变(2)指向的输出设备,所以它仍然指向终端

在第二种情况下,将stdout(1)重定向到一个文件。然后将stderr(2)指向1指向的同一个位置,即文件,因此错误消息将转到该文件。

有一个清晰的示例(与您的示例类似)说明顺序的重要性,并解释了差异。以下是摘录的相关部分(重点):

请注意,重定向的顺序很重要。例如 命令

ls>dirlist 2>&1

指示标准输出(文件描述符1)和标准错误 (文件描述符2)添加到文件目录列表,而

ls 2>&1>目录列表

仅将标准输出定向到文件目录列表,因为标准 标准输出之前的标准输出副本出错 输出被重定向到目录列表。

从POSIX的角度解释它

混淆是由于一个关键的差异造成的
重定向不是通过使左操作数(
stderr
)指向右操作数(
stdout
),而是通过制作右操作数的副本并将其分配给左操作数。从概念上讲,赋值是通过复制而不是引用

因此,从左到右读取,这就是Bash的解释:
ls>dirlist 2>&1
意味着将
stdout
重定向到文件
dirlist
,然后将
stderr
重定向到当前的
stdout
文件(该文件已经是
dirlist
)。但是,
ls 2>&1>dirlist
会将
stderr
重定向到当前
stdout
的任何位置(即屏幕/终端),然后将
stdout
重定向到
dirlist

重定向为:

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

  • >文件2>&1

    • >file
      首先将stdout(文件描述符
      1
      ,通过不在
      前面加文件描述符编号表示)重定向到输出文件
      file
    • 2>&1
      然后将stderr(
      2
      )重定向到已重定向的stdout(
      1
    • 最终的结果是两个原始流都会出现在
      文件中
  • 2>&1>文件

    • 2>&1
      首先将stderr重定向到原始stdout;由于文件描述符
      2
      不参与进一步的重定向,因此stderr输出将转到在该点定义的任何stdout,即原始stdout,因为这是第一次重定向。
      • 从技术上讲,原始stdout文件描述符是重复的,而这个重复就是stderr所指的,这解释了为什么它不受stdout稍后重定向的影响
    • >文件
      然后将原始stdout重定向到
      文件
      ——但这对已经锁定的stderr重定向不再有任何影响
    • 净效果是,只有直接发送到stdout的输出被捕获到
      文件中,而发送到stderr的输出被输出到(原始的、未定向的)stdout

基本正确,但我对第四句“但是”的措辞提出质疑
ls: *.xyz: No such file or directory
ls -al *.xyz 2>&1 1> files.lst