从标准输入创建临时文件

从标准输入创建临时文件

假设我有一个标准输入流文件内容和一个期望的命令文件名作为参数,我想在由标准输入流的文件内容组成的文件上运行该命令。

例如,代替命令

imageviewer mouse.jpg

我想要一些神奇的线条magic,使它相当于

cat mouse.jpg | magic

这在ormagic中会是什么样子?zshbash

最好,我希望它看起来像

cat mouse.jpg | submagic | xargs imageviewer

也就是说,我想submagic从标准输入流创建一个临时文件并输出创建的文件的文件名。

这些行magicsubmagic应该是仅使用 bash 或 zsh 命令、它们的内置命令、GNU coreutils 等的 shell 管道。


这就是整个问题。下面只是澄清和背景,因为人们一直误解我的意思。


好吧,所以我以为我说清楚了,但似乎我没有说清楚:我真的想要有一个管道做相当于

imageviewer mouse.jpg

正好开始cat mouse.jpg | …。也就是说,我真的确切地一条线magicsubmagic类似的确切地上面的管道有效——我的问题是字面意思。

这尤其意味着以下建议的解决方案不起作用:

  • 开始管道tmpfile = $(mktemp); cat mouse.jpg | …
  • 将其重写为imageviewer =(cat mouse.jpg)
  • 将其重写为echo mouse.jpg | xargs imageviewer
  • 使用函数或二进制文件来解决它,例如通过定义function magic () { … }

可以说,我感兴趣的是是否可以编写一个别名alias magic='…',或者alias submagic='…'使上述管道之一能够工作,并且这些别名的定义仅包含 bash 或 zsh 命令、GNU coreutils 等 -没有什么是自己写的。

另一条评论。你认为imageviewerfehsxiv某事。

背景。当我尝试使用我的邮件客户端打开邮件中附加的多个图像文件时,我想到了这个问题neomutt。 Neomutt 提供标记附加文件,然后将文件内容通过管道传输到您可以输入的命令行。因此,在这里,我只能给出一个在给定标准输入流上执行某些操作的命令行。这就是问题的来源。但我对原来的问题不感兴趣,而只对这个问题感兴趣。

答案1

至少bash,使用流程替代:

utility <( some_other_utility )

这将呈现utility一个文件名。当utility打开文件并从中读取时,它将读取some_other_utility.


你的例子:

cat mouse.jpg | submagic | xargs imageviewer

我假设这是为了发送文件名 mouse.jpgimageviewer,因为通过 发送 JPEG 文件的内容没有意义xargs

这可以通过以下方式完成

echo 'mouse.jpg' | xargs imageviewer

或者

xargs imageviewer <<<'mouse.jpg'

bash

mouse.jpg发送to的内容imageviewer可以通过

cat mouse.jpg | imageviewer /dev/stdin

或者,使用过程替换,

imageviewer <( cat mouse.jpg )

使用临时文件:

tmpfile=$(mktemp)
cat mouse.jpg >"$tmpfile"

imageviewer "$tmpfile"

rm "$tmpfile"

可能,

tmpfile=$(mktemp)
cat mouse.jpg | { cat >"$tmpfile"; echo "$tmpfile"; } | xargs imageviewer
rm "$tmpfile"

该管道依赖于这样一个事实:它将xargs等待执行,imageviewer直到它从管道的中间部分读取文件名。在创建临时文件之前,中间命令不会输出文件名。

答案2

在澄清submagic问题后,我编辑了答案。

zsh可以从命令的输出中创建一个临时文件=( ... )。与<( ... )可能使用设备文件(如/dev/fd...命名管道)相反,该表单=( ... )创建可查找的临时文件。看http://zsh.sourceforge.net/Doc/Release/Expansion.html#Process-Substitution

假设这cat mouse.jpg只是将图像数据发送到 stdout 的任何命令的示例,您可以使用

imageviewer =(cat mouse.jpg)

如果您需要 zsh 创建的临时文件具有特定的扩展名,您可以设置TMPSUFFIX特殊变量):

(TMPSUFFIX=.jpg; imageviewer =(cat mouse.jpg))

第二次更新

如果你坚持语法

cat mouse.jpg | submagic | xargs imageviewer

可以创建一个submagic类似于 Kusalananda 的答案中已经提出的命令的脚本。

#! /bin/sh

# A fixed name allows multiple runs without creating lots of files and
# allows a simple script to remove the file afterwards.
TMPFILE=/tmp/submagic.tmp.jpg
rm -f "$TMPFILE" && cat > "$TMPFILE" && echo "$TMPFILE"

与 shell 机制相反,这样的机制在运行后=( cat mouse.jpg )不会删除。$TMPFILEimageviewer

如果您可以在运行后运行第二个脚本,imageviewer如果它知道名称,则可以删除该文件。

脚本submagic-cleanup

#! /bin/sh

# A fixed name allows a simple script for cleaning up.
TMPFILE=/tmp/submagic.tmp.jpg
rm -f "$TMPFILE"

然后你就可以跑了

cat mouse.jpg | submagic | xargs imageviewer
submagic-cleanup

答案3

为了满足您的问题的确切要求,您可以执行以下操作:

cat mouse.jpg | { tf=$(mktemp); cat >"$tf"; echo "$tf"; } | xargs imageviewer

相关内容