如果退出代码为 0,我如何才能将 stdout 写入文件?

如果退出代码为 0,我如何才能将 stdout 写入文件?

海绵命令“吸收标准输入并将其写入文件”,这使我们可以通过管道在同一个文件之间进行传输。我想做类似的事情,我通过管道连接到类似海绵的实用程序,但如果源命令失败(具有非零退出),我希望该类似海绵的实用程序保持目标文件不变。

大致如下:

cue export package.cue | prettier --stdin-filepath .json
 | spongelike --abort-on-non-zero package.json

(我知道我可以并且已经将这个特定的管道重写为两个单独的命令,但我可以看到这在其他更棘手的场景中很有用。)

答案1

cmd1 | cmd2cmd1cmd2中同时启动并且都是 shell 的子级。

cmd2无法知道何时cmd1死亡,也无法获取其退出状态。只有父级(这里是 shell)可以。

因此,如果有一个命令可以执行您想要的操作,则无法将其调用为:

cmd | that-command output-file

它必须是:

that-command output-file cmd

在子进程中启动,通过管道收集其标准输出和/或将其存储在某个地方(内存或临时文件),等待子进程,如果成功,则打开 that-command并转储那里保存的输出。cmdoutput-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'

或已安装并支持该功能的任何其他 shellpipefailksh 选项的 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 并防止破坏。

相关内容