iru*_*var 3 linux bash file-descriptors
我有这个文件:
1
2
3
4
Run Code Online (Sandbox Code Playgroud)
当我paste以这种方式奔跑时
paste - - <file
Run Code Online (Sandbox Code Playgroud)
这结果
1 2
3 4
Run Code Online (Sandbox Code Playgroud)
到目前为止这么好,标准输入(重定向自file)被传递两次,paste因此奇数和偶数行成对打印。
但是,当这更改为
paste - /dev/fd/0 <file
Run Code Online (Sandbox Code Playgroud)
输出变成
1 1
2 2
3 3
4 4
Run Code Online (Sandbox Code Playgroud)
paste似乎打开了file两次(导致内核文件表中有两个不同的条目?),一次用于-参数,一次用于/dev/fd/0.
我茫然地解释这一点-如果我解释这个正确的,既-和/dev/fd/0应该被引用,因此单内核文件表项paste应该得到相同的结果与前面的情况。
这是 Linux 特有的。虽然在大多数 Unices 上,opening/dev/fd/n或多或少与dup(n)(获取与fd 上相同的打开文件描述的文件描述符n)相同,但在 Linux 上,/dev/fd/n是文件描述符上打开的文件的符号链接n。
所以,在 Linux 上:
paste - /dev/fd/0 < file
Run Code Online (Sandbox Code Playgroud)
是相同的:
paste - file < file
Run Code Online (Sandbox Code Playgroud)
(或paste file file)。
两个 fds(0 代表-和通过打开/dev/fd/0或获得自己的file)是独立的,并且在文件中有自己的光标。
您还会注意到,在 Linux 上,您不能将 /dev/fd/n 与套接字一起使用。
通常在 Linux 上,您只想/dev/fd/n与管道一起使用。但在这种情况下
cat file | paste - /dev/fd/0
Run Code Online (Sandbox Code Playgroud)
(或切换到非基于 Linux 的操作系统)不会真正有帮助。paste - -有效,因为paste在这两种情况下都知道它是标准输入。但不是在这里,所以它会从-(fd 0 到管道)读取整个块(而不是一行),然后从 /dev/fd/0读取另一个块(Linux 上同一管道的独立 fd,但是这些 fds 是否指向相同的打开文件描述对于管道来说并不重要)。两个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
Run Code Online (Sandbox Code Playgroud)