我可以访问带有作业调度程序 (Slurm) 的分布式计算/服务器场,该调度程序为每个并行作业提供从1
到 的整数 ID n
(我知道 的值n
,在下面的示例中为n = 10
)。
我用来find -maxdepth 1 -name '2019 - *'
查找要作为参数传递给程序的文件名列表。
示例文件名:
2019 - Alphabet
2019 - Foo Bar
2019 - Reddit
2019 - StackExchange
顺序并不重要。所有匹配的文件只能使用一次。
这是我可以使用的“模板”脚本的示例:
#!/bin/bash
# in this case, from i = 1 to i = 10
#SBATCH --array=1-10
# pseudocode begins
# it is given that filename_array has 10 unique elements
filename_array="$(find -maxdepth 1 -name '2019 - *')"
# SLURM_ARRAY_TASK_ID is the value of i, from i = 1 to i = 10
filename=filename_array[$SLURM_ARRAY_TASK_ID]
# pseudocode ends
./a.out "$filename"
这或多或少是它的作用(但每个进程并行运行在不同的计算机上):
./a.out "./2019 - Alphabet" &
./a.out "./2019 - Foo Bar" &
./a.out "./2019 - Reddit" &
./a.out "./2019 - StackExchange" &
如何编写一个 bash 脚本,为 给出的每个文件名运行一次模板脚本find -maxdepth 1 -name '2019 - *'
?
答案1
使用可能find
是一个错误,特别是当您只对当前目录中的文件感兴趣时。您可以只使用 shell glob 模式。
#/bin/sh
for f in '2019 - '*
do
[ -f "$f" ] && ./a.out "$f" &
done
对其作为文件的测试是为了可移植性。如果您正在使用,bash
则可以使用shopt -s nullglob
将不匹配的模式扩展为无内容而不是其本身,因此如果没有匹配的文件,则使循环运行零次而不是一次。然而,可移植性很好,可以处理诸如与模式匹配的目录名称之类的情况。
显然需要的是一个“模板脚本”,但我对这意味着什么了解有限。
也许
#!/bin/bash
# magic string for slurm to run on 10 hosts
#SBATCH --array=1-10
filename_array=( '2019 - '* )
filename=${filename_array[$SLURM_ARRAY_TASK_ID-1]}
./a.out "$filename"
是什么?
编辑:另一个需求更改。支持模式的正则表达式。
#!/bin/bash
# magic string for slurm to run on 10 hosts
#SBATCH --array=1-10
readarray -d '' filename_array < <( find . -maxdepth 1 -regex '.*2019 -.*' -print0 | sort -z )
filename=${filename_array[$SLURM_ARRAY_TASK_ID-1]}
./a.out "$filename"
答案2
你能用吗$SLURM_JOB_NODELIST
?
在这种情况下,GNU Parallel 似乎是一个显而易见的解决方案:
find -maxdepth 1 -name '2019 - *' |
parallel --slf $SLURM_JOB_NODELIST --wd . ./a.out {}