1

我正在努力理解命令重定向/重用......

我知道有组合输出的<(...) <(...)方法和$( ... && ... )技术。但我并不完全理解有什么区别(我意识到(...)转储你在一个新的 shell 中,导致你可能会跳转 dirs 并丢失你没有导出的任何变量,但我不确定它如何影响一般重定向方案),在浏览了以下示例和说明后,我仍然对如何进行一对多重定向感到困惑:
Advanced Bash Scripting Guide 1
Advanced Bash Scripting Guide 2

我自己尝试使用它的尝试大多导致“模糊重定向”错误。

例如,假设我想做一个由下面的伪代码给出的单行

    CMD 1 && CMD 2 && CMD 3 --> (1)  
    CMD 4 (1) --> (2)
    CMD 5 (1) --> CMD 6 --> (3)
    CMD 7 (2) && CMD 8 (3) --> (4)
    CMD 9 (2) --> (5)
    CMD 10 (2) (3) -->(6)
    VAR= echo (4) && echo (5) && echo (6)

或作为流程图

CMD 1 +CMD 2 && CMD 3 
    |\
    | ---> CMD 5 ------> CMD 6-----\
    V                     /         V
    CMD 4 ----------------u--------> CMD 10
     | \                  V           /
     |   -------->CMD 7 + CMD 8      /
     V             |                /
    CMD 9          |               /
      \            |              /
       \           V             /
        --------> VAR <----------

其中输出被指定为-->;在另一个操作中重用的存储由-->(#); 和组合操作由 给出&&

我目前不知道如何在没有冗余代码的情况下在一行中执行此操作。

我想真正掌握命令重定向,这样我就可以制作一些强大的单行代码。

希望这足够清楚......如果您需要它们,我可以为命令提供概念证明示例,但伪代码应该会给您这个想法。

4

3 回答 3

2

回复您的评论:

sort <(cd $CURR_DIR && find . -type f -ctime $FTIME) \ 
    <(cd $CURR_DIR && find . -type f -atime $FTIME) \ 
    <(cd $CURR_DIR && find . -type f -mtime $FTIME) | uniq

可以写成(我相信这更清楚)

(find . -type f -ctime $FTIME && find . -type f -atime $FTIME \
    && find . -type f -mtime $FTIME) | sort | uniq

给定三个程序,其中一个产生“a”或“z”作为输出。生成一个字符串,其中包含已排序的输出以及作为单行的唯一输出:

mkfifo named_pipe{1,2,3}; (echo z ; echo a ; echo z) > named_pipe1 & \
    tee < named_pipe1 >(sort > named_pipe2) | sort | uniq > named_pipe3 & \
    output=$(echo sorted `cat named_pipe2`; echo unique `cat named_pipe3`); \
    rm named_pipe{1,2,3}

生产sorted a z z unique a z

关于此解决方案,您可能会注意到的一件事是它被拆分,以便每个命令分组都有自己的行。我想我在这里得到的是一个衬里可能很酷,但通常清晰度更好。

其工作原理是使用名为 tee 和命名管道的程序。命名管道与匿名管道完全相同,例如。cat words.txt | gzip,除了它可以从文件系统中引用(但没有实际数据写入文件系统)。请注意,写入命名管道将阻塞,直到另一个进程正在从命名管道读取。我一直无缘无故地在这里使用管道,只是为了让您了解如何使用它们。

正如其他人所指出的,Tee 可以将输入复制到多个输出。

于 2012-03-14T10:11:09.080 回答
2

在这篇文章中,您的问题有某种答案的开始: 如何使用 Unix(或 Windows)中的(最好是未命名的)管道将一个进程的标准输出发送到多个进程?

使用 tee 和 >(命令)。但是您的示例相当复杂,很难想象没有临时存储(变量或文件)的单行解决方案,仅通过组合命令(Unix 方式,是的!)。

我的意思是,如果您同意按顺序启动多个命令,可能会更容易(但它不再是单行)......

即使用更复杂的语言(比如 python)编写这种表达式也会很复杂。

于 2012-03-14T08:26:27.540 回答
1

你有几个不同的问题要解决。

  1. 您需要一个输出作为其他几个命令的输入。你可以用tee >(cmd1) | cmd2. 请参阅此答案:如何使用 Unix(或 Windows)中的(最好是未命名的)管道将一个进程的标准输出发送到多个进程?

    另一种方法是创建一个文件。我通常更喜欢文件方法,因为它允许调试最终脚本。为避免造成混乱,请创建一个临时工作目录,然后将其删除trap "..." EXIT

  2. 您需要将多个命令的输出组合为单个命令的输入。在此处使用子 shell:( CMD 1 ; CMD 2 ) | CMD 3将 1 和 2 的输出组合为 3 的输入。

  3. 您需要将上述两者混合使用。您可以创建其他文件描述符,但每个文件描述符只能读取一次。用于cat组合它们并tee创建副本。

这应该都是可能的,但有一个缺点:如果某些东西不起作用或出错,您将永远无法找到错误。

因此:创建工作目录并使用文件。如果将其放入/tmp,则数据将不会写入磁盘(在现代 Linux 系统上,/tmp是 ram 磁盘),这将像管道一样运行,除非您拥有大量数据并且您将能够维护脚本。

于 2012-03-14T09:06:33.033 回答