Bash:重定向文件描述符

4
我希望有人能解释一下一个现象。正如标题所示,我正在学习文件描述符的重定向。在学习过程中,我遇到了一个关于重定向符号使用的问题,特别是在设置永久重定向时。我注意到,在某些情况下,无论我使用 < 还是 > 都似乎没有关系。例如,使用以下脚本:
#!/bin/bash

#Setting file descriptor 3 to redirect  to STDIN
exec 3<&0

#Setting STDIN to read from input file
exec 0<inputFile


while read var
do
    echo "$var"

done

#Setting STDIN to read from file descriptor 3 which is redirected to the default STDIN
exec 0<&3

read -p "Enter a word:" word

echo "$word"

令我惊讶的是,在语句 exec 3<&0exec 0<&3 中使用符号 >< 似乎并不影响结果。在这些语句中,如果交换重定向符号,似乎仍然得到完全相同的结果。对我来说,显然对以下行进行相同类型的更改是可以的:
exec 0<inputFile

对比。

exec 0>inputFile

由于将STDIN重定向到文件并不等同于将文件重定向到STDIN,因此不会产生相同的结果。

所以我的问题是:

  1. < vs >:

    # Why aren't there any differences between these two statements?
    exec 3<&0
    exec 3>&0
    
  2. 3<&0 vs 0<&3:

    # Why is there a difference between these two statements?
    exec 3<&0
    exec 0<&3
    
这种重定向方式对我来说已经很难理解和区分了,如果有任何解释将不胜感激。

1
我稍微编辑了你的帖子,以反映你所问的两个问题。如果您不喜欢我的更改,请随意回滚或进一步编辑! - gniourf_gniourf
1个回答

6
当复制文件描述符时,无论您使用<还是>,都会调用dup2,这不重要。
关闭文件描述符时也是如此。您可以使用n>&-n<&-

然而为什么0<&3不等于3<&0

这在我链接的dup2规范中有说明。
int dup2(int fildes, int fildes2);

The dup2() function shall fail if:

[EBADF]

The fildes argument is not a valid open file descriptor or the argument fildes2 is negative or greater than or equal to {OPEN_MAX}.

对于exec 0<&3的情况,Bash会调用dup2(3,0)函数,因为此时我们处于fildes=3的情况下,而此时该文件描述符不是有效的打开文件描述符,所以Bash确实会收到EBADF错误。您可以使用strace轻松检查:

$ strace -e dup2 bash -c 'exec 0>&3'
dup2(3, 0)                              = -1 EBADF (Bad file descriptor)
bash: 3: Bad file descriptor
dup2(10, 0)                             = 0
+++ exited with 1 +++

好的,那很有道理。也许我的困惑来自于我的书将其描述为“重定向”文件描述符,而实际上应该将其视为“复制”它们?但是,为什么'0<&3'不等同于'3<&0'呢? - Dr.Tautology
1
好的,我现在完全明白了。虽然在你的编辑中提到“fildes=3,在此时并不是一个有效的打开文件描述符”,但这并不适用于脚本中的最后一个exec语句。在那个时候,第3个文件描述符已经被打开了,对吗?然而,根据你在这里所阐述的情况,我认为最好的思考方式是复制而不是重定向。如果我这样考虑,所有的困惑都会消失。"0<&3"和"3<&0"不同,因为复制3并不等同于复制0。非常感谢给我带来这种清晰度。 - Dr.Tautology
1
@Dr.Tautology:没错! - gniourf_gniourf

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接