有人问如何将两个命令的输出作为文件传递给另一个命令,他们得到了下面的答案。
( cmd1 | ( cmd2 | ( main_command /dev/fd/3 /dev/fd/4 ) 4<&0 ) 3<&0 )
我需要打开包装。
说我有一个文本文件some_file
,我希望将其作为输入传递给main_command
。main_command
将两个文件作为输入。如果我想main_command
与some_file
命令的输出配合使用cmd2
,一种方法是
( cmd2 | ( main_command some_file /dev/fd/4 ) 4<&0 )
main_command some_file /dev/fd/4
。这简直是传递文件some_file
,并/dev/fd/4
作为参数main_command
。4<&0
部分说,这stdin
将指向文件描述符4
。cmd2 |
将的输出cmd2
与后面的任何输入连接起来。我的问题是:
编辑:我应该说,如果我的逻辑是正确的,那么就没有必要回答1。
这是一个非常复杂的命令。我已经在最后直接回答了您的问题,但是直到那时所有这些都在解压缩命令本身。我尝试过综合一些,因此可能比您在某些地方需要的细节还要多。
( x y z )
意味着从当前的shell中派生一个新的shell,以x y z
在其中执行(然后返回到当前shell)。子外壳程序继承了当前外壳程序的所有内容,但是是一个独立的过程:这意味着它可以将输入通过管道传递到其中,并且可以在内部进行自己的环境更改而不影响父级。
每个打开的文件都有一个与之关联的数字“文件描述符”。在本文中,“文件”包括任何类型的输入或输出流,包括实际文件,套接字和标准I / O流。这些数字是可以直接与Cread
函数一起使用以标识您正在谈论的流,与操作系统提供的相应系统调用以及所有其他IO函数一起使用的句柄。
4<&0
执行重定向,将标准输入文件描述符(0)克隆为文件描述符4。这意味着FD 0将被复制到4,而不是相反。在这种情况下,它将修改重定向之前的子外壳程序的打开文件。目前,这只是为输入流创建另一个“名称”。不过,关键的一点是,此后两个名称彼此独立:即使FD 0更改为引用其他名称,并且这两个名称分开,FD 4仍将始终引用相同的流。
/dev/fd/4
是程序访问其自己的打开文件描述符的(非标准)方式。在Linux上,它是的符号链接/proc/self/fd
,它可验证当前进程的文件描述符表。程序可以open("/dev/fd/4", O_RDONLY)
获取指向该程序在FD 4上具有的流的文件句柄(例如其4
自身)。就程序而言,这只是一个常规文件,可以像打开其他文件一样打开,关闭和读取。因为打开的文件描述符是由子main_command
进程继承的,所以文件描述符与其内部的子shell具有相同的文件描述符4,因此/dev/fd/4
在这里也可以工作。
cmd2 | x
运行cmd2
,并将其标准输出连接到的标准输入-或FD 0- x
。在您的命令中,x
是subshell表达式。
我们的整体命令
cmd2 | ( main_command /dev/fd/4 ) 4<&0
然后分为三个主要部分:
cmd2
并将其输出传输到( main_command /dev/fd/4 ) 4<&0
。4
另一名由确定的流0
(标准输入)( main_command /dev/fd/4 )
。main_command
使用/dev/fd/4
作为参数运行,(可能会)将其作为文件打开并从中读取,从而获得的输出cmd2
。最终的效果是main_command
获取一个可以打开的路径名参数,并从中读取其输出,cmd2
这与Bash进程替换完全相同main_command <(cmd2)
:实际上,这很可能会/dev/fd/63
作为参数,否则在内部进行类似的处理。
对于完整的命令
( cmd1 | ( cmd2 | ( main_command /dev/fd/3 /dev/fd/4 ) 4<&0 ) 3<&0 )
我们有嵌套的子外壳程序:这是因为我们要制作两个标准输入副本,但这是两个不同的标准输入:一个是的输出cmd1
,通过管道连接到较大的子外壳中后放入FD 3,另一个是输出的cmd2
,这是正在管道输送到最内壳层后放入FD 4。这两个0
小号均指标准输入,但每个命令的标准输入是不同的,因为我们有一些不同的管道进去。
我认为这是问题中最令人困惑的部分。每个命令(在这里是每个子shell)都有其自己的标准输入,从cmd1
/管道输入cmd2
,并且唯一的标准输入流被别名为3
or 4
。这些打开的文件描述符由subshell和子命令的下一层继承,因此/dev/fd/3
,即使标准输入现在指向其他内容,在最里面的命令所引用的内容也与外部相同。
尽管对某些命令而言,使括号稍微更健壮,但并非严格要求使用括号,这可能是一种很好的做法。内部的是:用于创建一个新的子流程的子流程,该子流程中可以具有自己的一组重定向,也可以管道传输其自己的标准输入流。
最里面的重定向实际上是多余的:cmd2 | main_command /dev/fd/3 /dev/stdin
因为没有对标准输入做进一步的更改,所以它也可以工作。
要直接解决您的问题:
我如何在问题开头解压缩命令?
至此,整个拆箱工作都已完成。
括号是做什么的?
括号会创建一个子shell,这是一个独立的shell进程,可以像使用其他任何命令一样使用它,包括将输入管道输送到其中,但是可以在内部执行普通的shell操作,例如重定向。
我对简单命令的解释正确吗?
部分地。4<&0
表示文件描述符4将指向stdin,并且重要的是指向当前称为stdin的文件-而不是标准输入的概念。/dev/fd/4
是“一切都是文件意义”中的“文件”,但更具体地说,它是一个路径名,打开该路径名后,便会退回FD 4。
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句