这海绵命令“吸收标准输入并将其写入文件”,这使我们可以通过管道在同一个文件之间进行传输。我想做类似的事情,我通过管道连接到类似海绵的实用程序,但如果源命令失败(具有非零退出),我希望该类似海绵的实用程序保持目标文件不变。
大致如下:
cue export package.cue | prettier --stdin-filepath .json
| spongelike --abort-on-non-zero package.json
(我知道我可以并且已经将这个特定的管道重写为两个单独的命令,但我可以看到这在其他更棘手的场景中很有用。)
答案1
在cmd1 | cmd2
、cmd1
和cmd2
中同时启动并且都是 shell 的子级。
cmd2
无法知道何时cmd1
死亡,也无法获取其退出状态。只有父级(这里是 shell)可以。
因此,如果有一个命令可以执行您想要的操作,则无法将其调用为:
cmd | that-command output-file
它必须是:
that-command output-file cmd
在子进程中启动,通过管道收集其标准输出和/或将其存储在某个地方(内存或临时文件),等待子进程,如果成功,则打开 that-command
并转储那里保存的输出。cmd
output-file
这可以通过 shell 脚本来完成,例如:
#! /bin/sh -
usage() {
printf >&2 'Usage: %s <output> <cmd> [<args>...]\n' "${0##*/}"
exit 1
}
[ "$#" -ge 2 ] || usage
output=$1; shift
tmp=$(mktemp) || exit
exec > "$tmp" 3< "$tmp"
rm -f -- "$tmp" || exit
"$@" 3<&- && cat <&3 3<&- > "$output"
(mktemp
还不是标准,但很常见)。
这里用作:
cue export package.cue | that-script package.json prettier --stdin-filepath .json
或者,检查两者是否cue
是否prettier
成功:
that-script package.json ksh -o pipefail -c '
cue export package.cue | prettier --stdin-filepath .json'
或已安装并支持该功能的任何其他 shellpipefail
ksh 选项的 shell(至少包括 zsh、bash、mksh、yash)。该选项将出现在 POSIX 标准的下一版本中,因此您sh
可能已经拥有它,在这种情况下,您还可以执行以下操作:
that-script package.json eval 'set -o pipefail
cue export package.cue | prettier --stdin-filepath .json'
请注意,该语句中运行的代码eval
可能会影响输出文件的创建方式。例如,与that-script output eval 'cd /some/dir; cmd'
,输出文件将在 中创建/some/dir
,您可以使用that-script output eval 'umask 077; set -o noclobber; cmd'
它来设置 umask 并防止破坏。