考虑以下文件:
$ find findtest
findtest
findtest/test1
findtest/test1/start.ksh
findtest/test2
findtest/test2/start.ksh
findtest/test3
findtest/test3/start.ksh
findtest/test4
findtest/test4/start.ksh
{}
我的问题是关于通话中的使用-exec
。它的工作原理正如我在指定结果文件时所期望的那样:
$ find findtest -name test[1-4] -exec ls -d {} \;
findtest/test1
findtest/test2
findtest/test3
findtest/test4
然而,在路径中使用时它似乎没有扩展:
$ find findtest -name test[1-4] -exec md5sum {}/start.ksh \;
md5sum: {}/start.ksh: No such file or directory
md5sum: {}/start.ksh: No such file or directory
md5sum: {}/start.ksh: No such file or directory
md5sum: {}/start.ksh: No such file or directory
如何使用find -type d -exec
访问较低层次结构的文件?我知道我可以使用这样的循环,但我很好奇是否可以在一次调用for
中完成它:find
$ for f in $(find findtest -name test[1-4]); do md5sum "$f"/start.ksh; done
d41d8cd98f00b204e9800998ecf8427e findtest/test1/start.ksh
d41d8cd98f00b204e9800998ecf8427e findtest/test2/start.ksh
d41d8cd98f00b204e9800998ecf8427e findtest/test3/start.ksh
d41d8cd98f00b204e9800998ecf8427e findtest/test4/start.ksh
答案1
这find 命令的 POSIX 标准仅要求用文件名替换独立的 {},并且仅替换第一个。使用{}/start.ksh
会导致未指定的行为。
仅包含两个字符“{}”的参数应替换为聚合路径名集,每个路径名按照聚合顺序作为单独的参数传递给调用的实用程序。任何两个或多个路径名集合的大小均应受到限制,以便实用程序的执行不会导致超出系统的 {ARG_MAX} 限制。如果存在多个仅包含两个字符“{}”的参数,则行为未指定。
如果 utility_name 或参数字符串包含两个字符“{}”,而不仅仅是两个字符“{}”,则 find 是否替换这两个字符或不更改地使用该字符串是实现定义的。
使用 Solaris find 执行所需操作的一种方法是使用以下命令:
find findtest -name "test[1-4]" -exec sh -c 'md5sum $1/start.ksh' foo {} \;
更快的方法是:
find findtest -name "test[1-4]" -exec sh -c 'for i; do md5sum "$i/start.ksh"; done' foo {} +
答案2
- 实际上,您的 shell
test[1-4]
在调用之前正在扩展find
。你需要逃避它'…'
{}
仅当它是一个单独的标记时才被视为模式
-exec
其本身通常成本较高,建议与尾随一起使用+
,或避免使用以利于喂食xargs
。
我知道我可以使用这样的 for 循环,但我很好奇是否可以在一个 find 调用中完成它:
find findtest -name 'test[1-4]' -print0 | xargs -0I{} -- md5sum '{}/start.ksh'
—md5sum
高效运行 — 一次性给出所有文件名。