如何“对包含文件夹内的多个子目录中的文件执行命令”,即 cd 进入包含文件的每个子目录并执行命令

如何“对包含文件夹内的多个子目录中的文件执行命令”,即 cd 进入包含文件的每个子目录并执行命令

我在不同的目录中有一个名为 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 

这是行不通的。我期待在这里得到一些帮助。请。

答案1

听起来像你想要的:

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 {} +

使用zshshell,您还可以执行以下操作:

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

exec(保存进程)不是必需的,因为zsh它已经隐式地用于子 shell 中运行的最后一个命令)。

$f:h扩展为$fhead (目录名)及其$f:tail t(基本名)。


例如,如果目录名称以换行符结尾,则 仍然有效;在某些情况下,使用dirname(or zsh's $var:h) 会给出更好的结果,但当获取 of 的路径dirname不包含任何或以字符/结尾时。/

相关内容