给定一个文件"foo.txt"
,由:
$ seq 1 10 > "foo.txt"
我正在尝试读取文件的第一行和最后一行,并且我开始将文件重定向到子shell,以便命令列表将依次使用该文件 - 每个命令都使用来自最后一个命令留下的点,我想:
$ (head -1; tail -1) < "foo.txt"
1
10
但是,如果我使用临时文件描述符尝试相同的操作,则输出结果不同:
$ (head -1; tail -1) < <(seq 1 10)
1
问题:
我不确定要命名<(seq 1 10)
的是什么,但这个临时文件描述符和常规文件描述符之间有什么区别( "foo.txt"
),这会导致子shell执行的行为不同吗?
如何在不实际创建文件的情况下实现将"foo.txt"
重定向到子shell但没有临时文件的相同行为。
答案 0 :(得分:7)
这只是一个缓冲问题。尝试:
cat foo.txt | ( head -1; tail -1)
你会(可能)看到同样的事情(头部消耗整个输入)。可能正在发生的事情是头部与常规文件的行为不同而不是管道,并且进程替换(这是<(cmd)
语法的名称)正在创建管道。 (在Linux中,来自Gnu coreutils的head
执行lseek
尝试重新定位它输出的最终换行符,但lseek
在管道上失败。)
还可以尝试:
(head -1; tail -1) < <(cat /usr/share/dict/words)
这里,head
仅消耗输入的第一页,尾部查看数据的最后一行。
您看到的行为定义不明确,因为没有标准规定允许使用多少数据头。如果您将head
替换为sh -c 'read line; echo "$line"'
,那么您将在所有情况下获得所需的行为。 (或者编写自己的工具来提供所需的head
行为 - 打印固定数量的行,同时不消耗更多行。)