文件描述符重复行为

文件描述符重复行为

我有这个文件:

1
2
3
4

当我paste以这种方式跑步时

paste - - <file

这个结果

1       2
3       4

到目前为止一切顺利,标准输入(重定向自file)被传递两次,paste因此奇数行和偶数行成对打印。

但是,当这更改为

paste - /dev/fd/0 <file

输出变成

1       1
2       2
3       3
4       4

paste似乎打开了file两次(导致内核文件表中有两个不同的条目?),一次用于参数-,另一次用于/dev/fd/0.

我无法解释这一点——如果我是在翻译的话正确的是,-和都/dev/fd/0应该引用单个内核文件表条目,因此paste应该产生与前一种情况相同的结果。

答案1

这是 Linux 特有的。虽然在大多数 Unices 上,打开/dev/fd/n或多或少与dup(n)(将文件描述符获取到相同的打开文件描述与 fd 一样n),在 Linux 上,/dev/fd/n是在文件描述符上打开的文件的符号链接n

所以,在 Linux 上:

paste - /dev/fd/0 < file

是相同的:

paste - file < file

(或者paste file file)。

这两个 fd(0和通过打开或-获得的自己的文件)是独立的,并且在文件中拥有自己的光标。/dev/fd/0file

您还会注意到,在 Linux 上,您不能将 /dev/fd/n 与套接字一起使用。

通常在 Linux 上,您只想/dev/fd/n与管道一起使用。但在这种情况下

cat file | paste - /dev/fd/0

(或者切换到非基于 Linux 的操作系统)并不会真正有帮助。paste - -有效,因为paste在这两种情况下都知道它是标准输入。但这里不是,所以它会从(fd 0 到管道)读取整个块(而不是单行)-,然后从 /dev/fd/0 读取另一个块(Linux 上到同一管道的独立 fd,但这些 fd 是否指向同一个打开文件描述或不对于管道来说并不重要)。两个read()s 都会读取文件的不同部分,但一次读取几行。

您需要告诉paste一次读取一个字节,这样在-从 读取一行之前它不会读取超过一行/dev/fd/0,如果不重新编译,您可能无法做到这一点。您也许可以使用paste一次读取其标准输入一个字节stdbuf,但可能不能/dev/fd/0

$ cat file | paste - /dev/fd/0
1
2
3
4
$ cat file | stdbuf -i1 paste - /dev/fd/0
1       2
        3
        4

相关内容