Find

如何“在包含文件夾內的多個子目錄中的文件上執行命令”,即 cd 到包含文件的每個子目錄並執行命令

  • March 30, 2022

我在不同的目錄中有一個名為 filename.sh 的文件。我正在嘗試同時送出此文件以在多個集群節點上執行。我需要在任何地方找到這個文件,cd 到它們的包含文件夾並執行命令“sbatch run_code.sh”這是我嘗試過的。

find . -mindepth 1 -type f -name filename.sh -exec sbatch run_code.sh {} \;

它可以工作,除了它從目前文件夾執行命令,該文件夾不包含執行程式碼所需的依賴項。

或者我傾向於這樣的for循環

for d in dirname; do 
 cd "$(dirname "$(find . -type f -name filename.sh)")" && sbatch run_code.sh)
done 

這是行不通的。我期待在這裡得到一些幫助。請。

聽起來像你想要的:

find . -name filename.sh -type f -execdir sbatch run_code.sh {} ';'

-mindepth 1是多餘的。它排除了.,但.無論如何都被-type f和排除了-name filename.sh

-execdir(來自 BSD),不是標準find謂詞,但如果您find支持-mindepth(儘管來自 GNU 也是非標準的),它也將支持-execdir.

-execdir正是為此。就像-exec它在所選文件的父目錄中執行命令一樣。在這裡,根據find實現,正在執行的命令將是sbatch run_code.sh ./filename.shsbatch run_code.sh filename.sh{}如果您不希望將filename.sh作為參數傳遞給命令,請刪除。

對於find不支持的實現-execdir,您可以執行以下操作:

find . -name filename.sh -type f -exec sh -c '
 cd "${1%/*}" && exec sbatch run_code.sh "${1##*/}"' sh {} ';'

${1%/*}$1,但刪除了最短的尾部匹配/*,所以它會表現得像"$(dirname -- "$1")"但更有效和更可靠¹。${1##*/}刪除最長的頭部匹配*/,給你一個類似basename的結果。

或者為了避免sh每個文件執行一個:

find . -name filename.sh -type f -exec sh -c '
 for file do
   (cd "${file%/*}" && exec sbatch run_code.sh "${file##*/}"
 done' sh {} +

使用zsh外殼,您還可以執行以下操作:

for f (./**/filename.sh(ND.)) (cd $f:h && sbatch run_code.sh $f:t)

exec(保存程序)不是必需的,因為zsh它已經隱式地用於子shell中執行的最後一個命令)。

$f:h擴展到$f’s head (dirname) 和$f:t它的tail (basename)。


例如,如果目錄名稱以換行符結尾,¹ 仍然可以工作;在某些情況下,使用dirname(或zsh’s $var:h)會產生更好的結果,儘管當獲取dirnameof 的路徑沒有任何字元/或以/字元結尾時。

引用自:https://unix.stackexchange.com/questions/697381