如何从find中得到第n个结果?

如何从find中得到第n个结果?

我可以访问带有作业调度程序 (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 {}

相关内容