如何批处理 sed 文件和重定向结果

how to batch sed files and redirect results

我想知道是否有一个单行程序可以批处理一个文件夹中的一组文件并将结果重定向到另一个文件夹。 我试过这样的事情:

find input_dir/ -name "PATTERN" | xargs -I {} sed 's:foo:bar:g' > output_dir/{}

例如,input_dir/ 有文件 A、B、C,我希望的结果是在 output_dir/ 中处理文件 A、B、C,具有相同的文件名。

我希望使用 {} 替换文件名并构建输出文件路径,但这没有用。

有人知道如何解决这个问题吗?或者其他更好的方法? 谢谢!

我的技巧是编写一个 shell 脚本来完成这项工作,然后 运行 通过 find 它。例如,您的操作可以写入脚本 munger.sh:

#!/bin/sh
for file in "$@"
do
    output="output_dir/$(basename "$file")"
    sed -e 's:foo:bar:g' "$file" > "$output"
done

find命令变为:

find input_dir -name "PATTERN" -exec sh munger.sh {} +

此 运行 脚本以文件名作为参数,方便地将大量文件名捆绑到 shell 脚本的单个调用中。如果您不再需要它,您可以在完成后简单地删除 munger.sh

是的,你可以做各种扭曲来按照你想要的方式执行命令(也许使用 find … -exec bash -c "the script to be executed" arg0 {} +),但这通常比编写一个相对简单的脚本并使用它然后扔掉它更难。引用的问题往往更少,例如,当您 运行 一个显式脚本时比您尝试在命令行上编写脚本时。如果您发现自己在与单引号、双引号和反斜杠(或反引号)作斗争,那么是时候使用如图所示的简单脚本了。

使用 GNU Parallel 看起来像这样:

find input_dir/ -name "PATTERN" | parallel sed s:foo:bar:g {} '>' output_dir/{/}

如果sed命令有特殊字符,那么你需要引用那些双:

find input_dir/ -name "PATTERN" | parallel sed 's:foo.\*:bar:g' {} '>' output_dir/{/}

分两步:

find input_dir/ -name "PATTERN" -exec cp -t output_dir/ {} +

sed 's:foo:bar:g' -i output_dir/*

或者,如果 output_dir 可能包含与 "PATTERN" 不匹配的文件:

find output_dir -name "PATTERN" -exec sed -e 's:foo:bar:g' -i {} +