
考慮以下文件:
$ 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
高效運作 — 一次給予所有檔案名稱。