我有这个文件:
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/0
file
您还会注意到,在 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