Singularity作业数组中循环生成BAM文件路径的问题求助
问题描述
我在用Singularity做作业数组测试,Singularity容器仅支持全局/环境变量作为输入。需要为279个目录生成对应BAM文件路径并赋值给变量,最初尝试的Shell循环如下:
for i in {1..279}; do SAMPLE="ls /path/to/sgdp_$i/input/*_chr.bam" done
但该循环执行完所有迭代后,变量仅保留最后一个目录(sgdp_279)的结果,而作业数组需要的是对应迭代目录的路径。我需要一种能随作业数组逐个生成对应路径的方式,而非一次性跑完整个循环。
目录结构(tree -h输出):
sgdp_001 ├── [ 4.0K] input │ ├── [ 83G] abh100_chr.bam │ └── [ 8.5M] abh100_chr.bam.bai ├── [ 4.0K] output ├── [ 83G] sample_chr.bam └── [ 8.5M] sample_chr.bam.bai sgdp_002 ├── [ 4.0K] input │ ├── [ 79G] abh107_chr.bam │ └── [ 8.5M] abh107_chr.bam.bai ├── [ 4.0K] output ├── [ 79G] sample_chr.bam └── [ 8.5M] sample_chr.bam.bai . . .
期望输出示例:
/path/to/sgdp_001/input/abh100_chr.bam /path/to/sgdp_002/input/abh107_chr.bam
注意:所有BAM文件前缀各不相同,仅后缀为_chr.bam。
解决方案
核心逻辑
作业数组的每个任务是独立进程,无需写循环一次性遍历所有目录,只需让每个任务根据自身索引值(调度系统不同变量名有差异,比如SLURM用$SLURM_ARRAY_TASK_ID)生成对应目录的BAM路径即可。
具体实现步骤
- 处理索引补零:因为目录命名是
sgdp_001这种三位格式,需要把任务ID补零成三位数字:
# 获取当前作业数组的任务ID,以SLURM为例 TASK_ID=$SLURM_ARRAY_TASK_ID # 补零为三位,比如1→001、10→010 FORMATTED_ID=$(printf "%03d" $TASK_ID)
- 安全匹配BAM文件路径:避免用
ls赋值(易引发解析问题),直接用通配符匹配:
# 单文件场景下直接赋值 SAMPLE=$(echo /path/to/sgdp_$FORMATTED_ID/input/*_chr.bam) # 更安全的数组存储方式(防止目录下出现多个BAM文件的情况) BAM_FILES=(/path/to/sgdp_$FORMATTED_ID/input/*_chr.bam) SAMPLE=${BAM_FILES[0]}
- 验证变量有效性:
echo $SAMPLE
作业数组提交示例(SLURM)
编写提交脚本submit_array.sh:
#!/bin/bash #SBATCH --array=1-279%10 # 一次并行运行10个任务 #SBATCH --job-name=singularity_bam #SBATCH --output=sgdp_%A_%a.out TASK_ID=$SLURM_ARRAY_TASK_ID FORMATTED_ID=$(printf "%03d" $TASK_ID) SAMPLE=$(echo /path/to/sgdp_$FORMATTED_ID/input/*_chr.bam) # 将SAMPLE作为环境变量传入Singularity容器执行命令 singularity exec --env SAMPLE=$SAMPLE your_container.sif your_target_command
提交命令:
sbatch submit_array.sh
原循环失效原因
原循环是在单个进程内遍历所有目录,每次迭代都会覆盖SAMPLE变量,最终仅保留最后一次赋值结果。而作业数组需要每个任务单独运行脚本,各自处理对应目录,无需全局循环。
内容的提问来源于stack exchange,提问作者Matteo
相关产品推荐
相关产品推荐

