Snakemake使用通配符时如何修改输出文件名
解决Snakemake输出文件名去除_Sx后缀的问题
我来帮你搞定这个文件名调整的需求!核心是要把输出里的_S1、_S2这类标识去掉,保留最前面的样本名(比如AAAAA、BBBBB),这里有两种优雅的实现方式,你可以根据自己的习惯选择:
方案一:直接修改样本名称提取逻辑(推荐)
这种方式从源头调整样本名的定义,让Snakemake直接生成你想要的输出文件名,不需要额外的重命名步骤。
修改你的样本变量定义部分,从原始文件名中提取不带_Sx的短样本名,同时建立短名和对应R1/R2文件的映射:
import glob import os # 只获取R1文件,避免重复处理 samples_r1 = sorted(glob.glob("input/*_R1_001.fastq")) # 创建短样本名到对应R1/R2文件的映射 sample_map = {} for r1_path in samples_r1: r1_basename = os.path.basename(r1_path) # 拆分出不带_Sx的短样本名,比如AAAAA_S1_R1_001.fastq -> AAAAA short_name = r1_basename.split("_S")[0] # 生成对应的R2文件路径 r2_path = r1_path.replace("_R1_", "_R2_") sample_map[short_name] = (r1_path, r2_path) # 提取去重后的短样本名列表,用于后续expand SHORT_NAMES = sorted(list(sample_map.keys()))
然后调整规则部分,让bwa规则通过映射获取正确的输入文件:
rule all: input: expand("output/{sample}_mapped.bam", sample=SHORT_NAMES), rule bwa: # 通过lambda函数从sample_map中获取对应样本的R1/R2文件 input: R1 = lambda wildcards: sample_map[wildcards.sample][0], R2 = lambda wildcards: sample_map[wildcards.sample][1] output: mapped = "output/{sample}_mapped.bam" params: ref = "refs/AF086833.fa" run: shell("bwa mem {params.ref} {input.R1} {input.R2} | samtools sort > {output.mapped}")
这样运行后,输出文件就会是AAAAA_mapped.bam、BBBBB_mapped.bam,完全符合你的需求。
方案二:添加重命名规则(适合需要保留中间文件的场景)
如果你想保留带_Sx的中间BAM文件,或者不想修改原有的样本提取逻辑,可以在bwa规则之后加一个重命名步骤:
首先调整样本变量,同时定义短样本名:
import glob import os samples = [os.path.basename(x).split("_R1_")[0] for x in sorted(glob.glob("input/*_R1_001.fastq"))] # 提取不带_Sx的短样本名 SHORT_NAMES = sorted(list(set([s.split("_S")[0] for s in samples]))) # 原有的带_Sx的样本名列表 FULL_NAMES = sorted(samples)
然后修改规则,先让bwa输出到临时目录,再通过rename_bam规则重命名到最终输出目录:
rule all: input: expand("output/{short_sample}_mapped.bam", short_sample=SHORT_NAMES), rule bwa: input: R1 = "input/{full_sample}_R1_001.fastq", R2 = "input/{full_sample}_R2_001.fastq" output: # 先输出到临时目录,保留带_Sx的文件名 mapped = "tmp/{full_sample}_mapped.bam" params: ref = "refs/AF086833.fa" run: shell("bwa mem {params.ref} {input.R1} {input.R2} | samtools sort > {output.mapped}") rule rename_bam: input: "tmp/{full_sample}_mapped.bam" output: "output/{short_sample}_mapped.bam" # 从full_sample中提取短样本名 params: short_sample = lambda wildcards: wildcards.full_sample.split("_S")[0] run: shell("mv {input} {output}")
记得提前创建tmp目录,或者在Snakemake中添加创建目录的规则(比如用shell("mkdir -p tmp")在某个规则里)。
内容的提问来源于stack exchange,提问作者BioFrank
相关产品推荐
相关产品推荐

