假设我有一个名为 的脚本script
,它读取stdin
一些结果并将其输出到屏幕上。
如果我想向它提供一个文件的内容,我会输入:
$ ./script < file1.txt
但是,如果我想以相同的方式将多个文件的内容提供给脚本,这可能吗?到目前为止我想出的最好的办法是:
cat file1.txt file2.txt > combined.txt && ./script < combined.txt
它使用两个命令并创建一个临时文件。有没有办法做同样的事情但绕过创建组合文件?
答案1
您可以使用cat
管道:
cat file1 file2 file3 ... fileN | ./script
cat
在这种情况下,./script
并发运行,数据通过某种 IPC 机制馈送,实际上,该机制是管道或套接字对,具体取决于 shell 和系统。
在 zsh shell 中,您还可以执行以下操作:
./script < file1 < file2 ... < fileN
其工作原理相同。当 stdin(或任何其他文件描述符)多次重定向输入时,zsh 会将其替换为管道的读取端,并cat
在内部实现类似的过程,以通过该管道的另一端按顺序提供输入。
./script
请注意,如果期望能够在文件中查找,例如当需要在倒带到开头后多次读取它或将其映射到内存中(例如mmap()
)时,这些方法将不起作用,因为这可以不能使用管道或套接字对来完成。在这种情况下,您需要一个临时的常规的(可寻找的) 文件,并且两个命令 (cat
和./script
) 不能同时运行。在 中zsh
,通过进程替换的形式可以使这变得更容易,=(cmd)
该过程替换扩展为包含 的输出的临时文件的路径,cmd
并在之后自动删除:
./script < =(cat file1 file2 file3 ... fileN)
shellfish
有类似的东西:
./script < (cat file1 file2 file3 ... fileN | psub -f)
答案2
如果您不想使用管道,可以使用输入重定向和进程替换:
./script < <(cat file1 file2)
答案3
要添加@Jonah Braun 的答案,如果您还需要将进程输出添加到脚本中,即您的文件可能不在磁盘上,但可以通过URL
使用curl
或类似工具进行访问。
像这样的东西可以用来获取stdout
多个进程并通过以下方式在脚本中使用它们stdin
这将是处理输入内容的脚本multi-input.sh
:
#!/usr/bin/env bash
while read line; do
echo $line
done
现在测试一下:
$ ./multi-input.sh < <(cat <(echo process 1) <(echo process 2) <(echo process 3))
输出:
process 1
process 2
process 3
<()
如果您愿意,可以file
使用将进程转换为虚拟进程,因此需要阅读它。它本身不需要它,因为它会做它所做的事情,连接虚拟或真实的文件。fd
<
cat