编写Bash循环批量处理目录及子目录下.sam文件生成同名.bam文件求助
修正你的Bash SAM转BAM脚本问题
我帮你梳理了这段脚本里的问题,主要是几个语法错误和逻辑小疏漏,下面是修正后的版本,以及问题的详细说明:
首先看修正后的脚本(更安全的版本)
这种写法能处理文件名包含空格、特殊字符的情况,避免出现意外:
find ~/data/finch_data/combruns_BF_genomes -name "*.sam" -type f -print0 | while IFS= read -r -d '' file; do # 去掉文件的.sam后缀,得到带完整路径的基础文件名 base_name="${file%.sam}" # 执行samtools转换,输出到原文件同目录的同名.bam文件 samtools view -Sb "$file" > "${base_name}.bam" done
如果你的系统支持Bash的globstar特性(先执行shopt -s globstar开启),也可以用更简洁的循环写法:
shopt -s globstar for file in ~/data/finch_data/combruns_BF_genomes/**/*.sam; do # 跳过不是文件的匹配项(比如目录名恰好以.sam结尾的情况) [[ -f "$file" ]] || continue base_name="${file%.sam}" samtools view -Sb "$file" > "${base_name}.bam" done
原脚本的问题分析
变量赋值缺少分隔符
原代码里name="${file%.sam}" dir=$(pwd $file)这一行,两个变量赋值之间没有用分号或换行分隔,Bash会把dir=...当成name变量值的一部分,直接触发语法错误。获取文件目录的方法错误
pwd $file是无效用法——pwd命令不接受文件路径参数,它只会输出当前工作目录。其实你根本不需要单独提取目录:${file%.sam}已经是带完整路径的文件名(比如/a/b/c.sam变成/a/b/c),直接加上.bam就是同目录的目标文件。如果非要单独取目录,可以用dirname "$file"或者"${file%/*}"。命令之间缺少分隔
原循环体里的多个命令(变量赋值、samtools命令)之间没有用分号或换行分隔,Bash无法正确解析每个独立的命令。文件名含特殊字符的风险
用for file in $(find ...)的方式遍历文件,如果文件名包含空格、换行或者其他特殊字符,会被Bash的分词机制拆分成多个元素,导致处理错误。用find -print0结合read -d ''的方式可以完美规避这个问题。
内容的提问来源于stack exchange,提问作者user5719890
相关产品推荐
相关产品推荐

