如何循环遍历 Bash 中列表的特定元素?

How can I loop through specific elements of a list in Bash?

我有一个文件列表存储在通过输入

获得的变量中
files="./*.fasta"

我想创建一个 for 循环,它将循环遍历:例如前 200 个元素、元素 201-400、元素 401-578。

我怎样才能做到这一点?我试过

for file in $files[1-200]; do 
    echo $file
done

但这显然行不通。

不推荐使用变量填充文件列表。最好的方法是使用数组!

您需要通过 shopt -s nullglob 启用 shell 选项来避免空 glob 扩展,这样如果没有找到文件,for-loop 就会正常退出。下面的示例显示了一次迭代 200 个文件。您可以根据需要更改索引,以便在 for-loop 中根据需要从 200-400 和 400-600 打印。

shopt -s nullglob
files=(*.fasta)

if (( "${#files}" >= 200 )); then
    for ((i=0; i<200; i++)); do
        printf '%s\n' "${files[i]}"
    done
fi

将它们放在一个数组中,然后使用子字符串扩展来获取批量文件。

files=(./*.fasta)
for ((i=0; i< ${#fasta[*]}; i+=200)); do
    process "${files[@]:i:200}" &
done

问题的解决方法可能有所不同。您可以使用 findxargs:

而不是使用 for 循环
find * -name '*.fasta' -maxdepth 0 -print0 | xargs -0 -n 200 -P 0 echo

find 将每个文件名传递给 xargs,后者又为每 200 个输入文件 (-n 200) 生成一个进程 (-P 0)。

此 one-liner 使用 -print0-0 标记以防您的文件名包含空格。

在这种情况下,for 循环构造不太理想。

或者,您可以使用 while 循环和内置的 readarray:

find * -name '*.fasta' -maxdepth 0 | while readarray -n 3 a && [[ ${#a} -ne 0 ]]
do
    echo ${a[@]}
done