如何将补丁作为管道的一部分应用?换句话说,如何修补标准输入?

如何将补丁作为管道的一部分应用?换句话说,如何修补标准输入?

我想mypatch.diff对标准输入应用统一差异并将结果输出到标准输出。

到目前为止,我已经尝试过:

patch -i mypatch.diff -o - -u originalfile

成功应用mypatch.diff并将结果打印到标准输出。但是,我仍然必须提供原始文件originalfile,而不是通过标准输入。

如果我尝试这样的事情:

patch -i mypatch.diff -o - -u -

然后补丁被拒绝:

patching file -
Hunk #1 FAILED at 1.
1 out of 1 hunk FAILED -- saving rejects to file -.rej

答案1

以下是 POSIX shell 的解决方案:

#!/bin/sh
patchstdin() (
    set -o errexit
    tmpdir="$(mktemp -d)"
    trap 'rm -rf -- "$tmpdir"' EXIT
    trap 'exit 1' HUP INT TERM
    cat >"$tmpdir/original"
    patch "$@" -o "$tmpdir/patched" "$tmpdir/original"
    cat "$tmpdir/patched"
)

假设yourcommand生成应该修补的输出,并且anothercommand期望收到修补的输出,您可以调用:

yourcommand | patchstdin -i patch.diff | anothercommand

注意mktemp不是 POSIX 的一部分。看为什么 POSIX 中没有 mktemp 命令?欲了解更多信息和如何在shell脚本中创建临时文件?用于 POSIX shell 的解决方案。

答案2

GNU 似乎没有patch这个选项。-表示 stdin for-i或 stdout for -o(for-r被解释为丢弃拒绝),但要修补的文件-被解释为-在当前目录中调用的文件。

此外,patch还需要根据要修补的文件名创建相关的具有.orig或后缀的文件。.rej

它看起来patch不允许你修补符号链接,因此在 Linux 上,使用 /dev/stdin 或 /proc/self/fd/0 不起作用。

如果使用zsh,您可以使用=(...)使用临时文件的进程替换形式:

patch -i mypatch.diff -r - -o - =(cat)

请注意,对于-o --r -,您需要 GNU patch2.6 或更高版本(请参阅犯罪犯罪)。

相关内容