了解破折号中的管道和重定向

重新导向

有人问如何将两个命令的输出作为文件传递给另一个命令,他们得到了下面答案

( cmd1 | ( cmd2 | ( main_command /dev/fd/3 /dev/fd/4 ) 4<&0 ) 3<&0 )

我需要打开包装。

说我有一个文本文件some_file,我希望将其作为输入传递给main_commandmain_command将两个文件作为输入。如果我想main_commandsome_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. 我如何在问题开头解压缩命令?
  2. 括号是做什么的?
  3. 我对简单命令的解释正确吗?

编辑:我应该说,如果我的逻辑是正确的,那么就没有必要回答1。

迈克尔·荷马

这是一个非常复杂的命令。我已经在最后直接回答了您的问题,但是直到那时所有这些都在解压缩命令本身。我尝试过综合一些,因此可能比您在某些地方需要的细节还要多。

括号创建一个子shell

( 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是subshel​​l表达式。


我们的整体命令

cmd2 | ( main_command /dev/fd/4 ) 4<&0

然后分为三个主要部分:

  1. 运行cmd2并将其输出传输到( main_command /dev/fd/4 ) 4<&0
  2. 4另一名由确定的流0(标准输入)( main_command /dev/fd/4 )
  3. 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,并且唯一的标准输入流被别名为3or 4这些打开的文件描述符由subshel​​l和子命令的下一层继承,因此/dev/fd/3,即使标准输入现在指向其他内容在最里面的命令所引用的内容也与外部相同。

尽管对某些命令而言,使括号稍微更健壮,但并非严格要求使用括号,这可能是一种很好的做法。内部的是:用于创建一个新的子流程的子流程,该子流程中可以具有自己的一组重定向,也可以管道传输其自己的标准输入流。

最里面的重定向实际上是多余的:cmd2 | main_command /dev/fd/3 /dev/stdin因为没有对标准输入做进一步的更改,所以它也可以工作。


要直接解决您的问题:

  1. 我如何在问题开头解压缩命令?

    至此,整个拆箱工作都已完成。

  2. 括号是做什么的?

    括号会创建一个子shell,这是一个独立的shell进程,可以像使用其他任何命令一样使用它,包括将输入管道输送到其中,但是可以在内部执行普通的shell操作,例如重定向。

  3. 我对简单命令的解释正确吗?

    部分地。4<&0表示文件描述符4将指向stdin,并且重要的指向当前称为stdin的文件-而不是标准输入的概念。/dev/fd/4是“一切都是文件意义”中的“文件”,但更具体地说,它是一个路径名,打开该路径名后,便会退回FD 4。

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章