基于子串匹配批量合并Fastq文件的Bash脚本优化方案咨询
基于子串匹配批量合并Fastq文件的Bash脚本优化方案咨询
嗨,很高兴看到你已经在尝试优化批量合并Fastq文件的脚本了!你的思路方向是对的,但我们可以让脚本更简洁、高效,同时避免一些潜在的问题,比如重复执行相同的合并操作或者依赖子shell带来的性能损耗。
先说说原脚本的小坑
你最初用samples.txt配合while read的方式,其实会遇到一个问题:read会把Apple*_S4当作普通字符串,不会解析通配符,所以后续的cat命令根本找不到对应的文件,这也是为什么你转向遍历文件思路的原因。
优化后的脚本方案
我们可以利用Bash的参数扩展直接提取文件名里的关键信息,避免调用cut、tr这类外部命令,同时通过关联数组去重,确保每个分组只处理一次:
#!/bin/bash # 先收集所有唯一的分组(水果前缀+样本标识) declare -A groups for file in *_trimmed_1.fastq; do # 提取水果前缀(自动去掉末尾数字,比如Orange1→Orange) fruit=${file%%[0-9]*} # 提取样本标识(比如从Orange1_S4_trimmed_1.fastq中拿到S4) sample=${file#*_} sample=${sample%%_trimmed_*} # 将"水果,样本"作为键存入关联数组,自动去重 groups["$fruit,$sample"]=1 done # 遍历每个唯一分组执行合并 for key in "${!groups[@]}"; do IFS=, read -r fruit sample <<< "$key" echo "正在处理 ${fruit}_${sample}..." # 合并R1端文件 cat "${fruit}"*_"${sample}"_trimmed_1.fastq > "${fruit}_${sample}_trimmed_1.fastq" # 合并R2端文件 cat "${fruit}"*_"${sample}"_trimmed_2.fastq > "${fruit}_${sample}_trimmed_2.fastq" done
脚本优势说明
- 无冗余执行:通过关联数组自动去重,避免了像你当前脚本那样多次处理同一个分组(比如Orange1_S4和Orange2_S4不会触发两次相同的合并)
- 更高效稳定:用纯Bash参数扩展代替外部命令,减少子shell创建,速度更快且兼容性更好
- 扩展性强:后续新增其他水果前缀(比如Banana)或样本标识(S6/S7),脚本无需修改就能自动适配
- 可读性高:每个步骤都有清晰的逻辑,后续维护起来更轻松
额外的实用小建议
- 怕不小心覆盖已有文件?可以在合并前加个判断:
if [ ! -f "${fruit}_${sample}_trimmed_1.fastq" ]; then cat "${fruit}"*_"${sample}"_trimmed_1.fastq > "${fruit}_${sample}_trimmed_1.fastq" fi - 想知道合并是否成功?可以添加错误检查:
if ! cat "${fruit}"*_"${sample}"_trimmed_1.fastq > "${fruit}_${sample}_trimmed_1.fastq"; then echo "合并${fruit}_${sample}_trimmed_1.fastq失败!" >&2 fi
备注:内容来源于stack exchange,提问作者user1967473
相关产品推荐
相关产品推荐

