透明地使用临时文件作为管道手段

透明地使用临时文件作为管道手段

我们中的许多人肯定都知道,让程序接受 stdin 输入总是一个好主意。很多程序都允许 *nix 环境。这让我们可以做一些很酷的事情,比如管道 echo "foo" | less。人们经常会发现这cat barfile | baz在逻辑上等同baz barfile于在幕后它只是读取字符串。

如今,有很多程序默认无法通过管道传输。有些程序有一个标志,允许上述行为,但很多程序不允许。

现在,我的问题是,临时文件管道是否存在?

现在,凭借我几乎不存在的编写 Bash 的能力,以及在 Google 上搜索了大约 5 分钟,我想出了这个

#!/bin/bash
if [ $# -ne 2 ]; then exit 1; fi
f=$(mktemp)
($1) > $f
if [ $? -eq 0 ]; then ($2 $f); else exit $?; fi
rm $f

调用这个 fpipe,我们可以做一些事情,比如fpipe 'wget -O- www.example.com' bazbaz 是一个我们无法通过管道传输但可以执行的程序baz file

我的问题是,我们怎样才能做得更好。我怀疑,随着 Bash 知识的增多,重写上述脚本以接受任意数量的参数将相当简单(这样我们就可以执行类似的事情,fpipe 'foo x' bar baz使用管道我们可以执行类似的事情foo x | bar | baz。哎,我们可能会将两者混合起来,最终得到类似的事情fpipe 'wget -O- www.example.org | rev' baz

是否存在实现此目的的现有构造?我相信我看到了某种构造foo x > bar < baz或类似的东西。我本以为这是一个相当常见的问题,但我的搜索没有带来任何结果。这意味着我要么搜索得不够仔细,要么我错过了一些相当明显的东西。

如果没有适当的方法(TM)来实现这一点,是否可以定义一个方便的语法?比如说,foo x |> baz | rev哪里|>几乎直接翻译成我的脚本。

PS:我知道我的 /script/ 非常脆弱和幼稚(例如在非 0 时退出);请随意发布一个更好的脚本。

答案1

这(原则上)在任何 shell 中都可以工作,但它需要“足够新的版本”的操作系统:

wget -O- www.example.com | baz /dev/stdin

/dev/stdin存在时,它通常是 的符号链接/proc/self/fd/0,因此如果您的盒子没有/dev/stdin,请检查/proc/self/fd/0


当然,管道的发明是 Unix 的伟大创新之一。1临时  中间文件在原则上是可以的,但可能会有性能成本,并且在

产生大量输出的程序| grep匹配极少行的正则表达式

您可能会遇到无法将文件(第一个命令的所有输出)放入磁盘的问题。因此,两全其美的方法是使用命名管道。这可以让您捕获某个程序2的标准输出 并将其作为路径名参数提供给另一个程序作为输入:

f=$(mktemp)  &&  rm -f "$f"  &&  mkfifo "$f"
$1 >> "$f" &
$2 "$f"
rm -f "$f"

第一个rm -f "$f"是必需的,因为它mktemp不仅生成文件名;它还创建文件。如果我们不删除它,将mkfifo失败。(或者,我们可以使用mktemp -u,它会生成文件名而不创建文件。)
___________
1 Unix 是否“发明”了管道尚有争议。根据Unix 分时系统的演变 (作者:Dennis M. Ritchie)(PDF),在 1972 年管道出现在 Unix 中之前,这个概念就已经以其他形式存在于其他地方。

2或者,一般来说,任何输出流;例如来自 或 cp somefile "$f"dd … of="$f"

答案2

使用足够新的 Bash 版本:

$ baz <(wget -O- www.example.com)

它被称为流程替代

答案3

如果给出了文件参数,或者应该从 stdin 读取行,则有两种方法可以使您的脚本执行相同的操作:

1)cat 文件,如果命令行中没有指定文件,则使用特殊文件名“-”

#!/bin/bash
[[ $# -eq 0 ]] && set -- "-"
n=0
while read line; do
    echo "$((++n)) $line"
done < <(cat "$@")

2)如果指定了文件,则将其内容复制到脚本的标准输入流

#!/bin/bash
[[ $# -gt 0 ]] && exec 0< <(cat "$@")
n=0
while read line; do
    echo "$((++n)) $line"
done

相关内容