使用find -execredirectstdout,而不用创build新的shell

我有一个只写入数据到stdout脚本。 我需要为多个文件运行它,并为每个input文件生成不同的输出文件,我想知道如何使用find -exec 。 所以我基本上尝试了几个变种(为了testing目的,我用catreplace了脚本):

find* -type f -exec cat“{}”>“{} .stdout”\;

但由于所有数据都被写入名为{}.stdout的文件,因此无法工作。

最终,我可以使它工作:

find * -type f -exec sh -c“cat {}> {} .stdout”\;

但是,虽然这个最新的forms与cat很好,我的脚本需要通过几个初始化脚本加载环境variables,因此我最终:

find * -type f -exec sh -c“initscript1; initscript2; …; myscript {}> {} .stdout”\;

这似乎是一个浪费,因为我已经在我的当前shell已经初始化的一切。

find更好的方法吗? 其他单线是受欢迎的。

Solutions Collecting From Web of "使用find -execredirectstdout,而不用创build新的shell"

一个简单的解决方案是将你的脚本包装一下:

 #!/bin/sh myscript "$1" > "$1.stdout" 

调用它myscript2并用find调用它:

 find . -type f -exec myscript2 {} \; 

请注意,虽然find的大多数实现允许您执行所做的操作,但是从技术角度讲,如果在-exec的参数列表中多次使用{} ,则find的行为是未指定的。

你可以用eval来做。 这可能是丑陋的,但也必须为此制作一个shell脚本。 另外,这一切都在一条线上。 例如

 find -type f -exec bash -c "eval md5sum {} > {}.sum " \; 

如果你导出你的环境变量,它们将已经存在于子shell中(如果你使用bash -c而不是sh -c ,而你的父shell本身就是bash,那么你也可以在父shell中导出函数 ,它们可以在小孩中使用;参见export -f )。

此外,通过使用-exec ... {} + ,可以将shell的数量限制为在命令行上传递所有参数所需的最小可能数量:

 set -a # turn on automatic export of all variables source initscript1 source initscript2 # pass as many filenames as possible to each sh -c, iterating over them directly find * -name '*.stdout' -prune -o -type f \ -exec sh -c 'for arg; do myscript "$arg" > "${arg}.stdout"' _ {} + 

或者,您可以直接在当前shell中执行执行:

 while IFS= read -r -d '' filename; do myscript "$filename" >"${filename}.out" done < <(find * -name '*.stdout' -prune -o -type f -print0) 

请参阅UsingFind通过find安全正确地执行批量操作; 和BashFAQ#24讨论使用进程替换( <(...)语法)来确保操作在父shell中执行。