使用 find -exec 重定向 stdout 而不创建新的 shell
- 2024-11-08 09:04:00
- admin 原创
- 26
问题描述:
我有一个只将数据写入的脚本stdout
。我需要对多个文件运行它并为每个输入文件生成不同的输出文件,我想知道如何使用find -exec
它。所以我基本上尝试了它的几种变体(我替换了脚本只是cat
为了可测试性目的):
find * -type f -exec cat "{}" > "{}.stdout" ;
但无法使其工作,因为所有数据都被写入名为的文件中{}.stdout
。
最终,我可以让它工作:
find * -type f -exec sh -c "cat {} > {}.stdout" ;
但是,虽然这个最新形式可以很好地与 配合使用cat
,但我的脚本需要通过几个初始化脚本加载环境变量,因此我最终得到:
find * -type f -exec sh -c "initscript1; initscript2; ...; myscript {} > {}.stdout" ;
这似乎是一种浪费,因为我当前的 shell 中已经初始化了所有内容。
有没有更好的方法来实现这一点find
?欢迎使用其他单行代码。
解决方案 1:
你可以用 eval 来做。这可能很丑陋,但为此编写一个 shell 脚本也是一件很丑陋的事情。另外,这一切都在一行上。例如
find -type f -exec bash -c "eval md5sum {} > {}.sum " ;
解决方案 2:
一个简单的解决方案就是给你的脚本加上一个包装器:
#!/bin/sh
myscript "$1" > "$1.stdout"
调用它myscript2
并使用 find 调用它:
find . -type f -exec myscript2 {} ;
请注意,尽管 find 的大多数实现允许您执行所做的事情,但从技术上讲,如果您{}
在 的参数列表中使用多次,则 find 的行为是未指定的-exec
。
解决方案 3:
如果您导出环境变量,它们将已经存在于子 shell 中(如果您使用bash -c
而不是sh -c
,并且您的父 shell 本身是 bash,那么您也可以导出父 shell 中的函数并让它们在子 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 \n -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 中执行。
- 2024年20款好用的项目管理软件推荐,项目管理提效的20个工具和技巧
- 2024年开源项目管理软件有哪些?推荐5款好用的项目管理工具
- 项目管理软件有哪些?推荐7款超好用的项目管理工具
- 项目管理软件哪个最好用?盘点推荐5款好用的项目管理工具
- 项目管理软件有哪些最好用?推荐6款好用的项目管理工具
- 项目管理软件有哪些,盘点推荐国内外超好用的7款项目管理工具
- 2024项目管理软件排行榜(10类常用的项目管理工具全推荐)
- 项目管理软件排行榜:2024年项目经理必备5款开源项目管理软件汇总
- 2024年常用的项目管理软件有哪些?推荐这10款国内外好用的项目管理工具
- 项目管理必备:盘点2024年13款好用的项目管理软件