假设我有一个标准输入流文件内容和一个期望的命令文件名作为参数,我想在由标准输入流的文件内容组成的文件上运行该命令。
例如,代替命令
imageviewer mouse.jpg
我想要一些神奇的线条magic
,使它相当于
cat mouse.jpg | magic
这在ormagic
中会是什么样子?zsh
bash
最好,我希望它看起来像
cat mouse.jpg | submagic | xargs imageviewer
也就是说,我想submagic
从标准输入流创建一个临时文件并输出创建的文件的文件名。
这些行magic
或submagic
应该是仅使用 bash 或 zsh 命令、它们的内置命令、GNU coreutils 等的 shell 管道。
这就是整个问题。下面只是澄清和背景,因为人们一直误解我的意思。
好吧,所以我以为我说清楚了,但似乎我没有说清楚:我真的想要有一个管道做相当于
imageviewer mouse.jpg
那正好开始和cat mouse.jpg | …
。也就是说,我真的想确切地一条线magic
或submagic
类似的确切地上面的管道有效——我的问题是字面意思。
这尤其意味着以下建议的解决方案不起作用:
- 开始管道
tmpfile = $(mktemp); cat mouse.jpg | …
- 将其重写为
imageviewer =(cat mouse.jpg)
- 将其重写为
echo mouse.jpg | xargs imageviewer
- 使用函数或二进制文件来解决它,例如通过定义
function magic () { … }
可以说,我感兴趣的是是否可以编写一个别名alias magic='…'
,或者alias submagic='…'
使上述管道之一能够工作,并且这些别名的定义仅包含 bash 或 zsh 命令、GNU coreutils 等 -没有什么是自己写的。
另一条评论。你认为imageviewer
是feh
或sxiv
某事。
背景。当我尝试使用我的邮件客户端打开邮件中附加的多个图像文件时,我想到了这个问题neomutt
。 Neomutt 提供标记附加文件,然后将文件内容通过管道传输到您可以输入的命令行。因此,在这里,我只能给出一个在给定标准输入流上执行某些操作的命令行。这就是问题的来源。但我对原来的问题不感兴趣,而只对这个问题感兴趣。
答案1
至少bash
,使用流程替代:
utility <( some_other_utility )
这将呈现utility
一个文件名。当utility
打开文件并从中读取时,它将读取some_other_utility
.
你的例子:
cat mouse.jpg | submagic | xargs imageviewer
我假设这是为了发送文件名 mouse.jpg
到imageviewer
,因为通过 发送 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 )
不会删除。$TMPFILE
imageviewer
如果您可以在运行后运行第二个脚本,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