You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何按中间目录名合并多子目录下的contigs.fasta文件?

问题描述

需求:将分散在多子目录中的contigs.fasta文件,按中间数字目录名(如1234)归类合并为单个concat.fasta文件,即使对应目录下仅存在一个文件也需执行合并操作,且希望避免复制文件到目标目录后再合并。

当前目录结构

my_project
+-- housecat
|   +-- 1234
|   |  +-- 1234_contigs.fasta
|   +-- 1290
|   |  +-- 1290_contigs.fasta
+-- jaguar
|   +-- 1234
|   |  +-- 1234_contigs.fasta
|   +-- 4567
|   |  +-- 4567_contigs.fasta
|   +-- 9876
|   |  +-- 9876_contigs.fasta
+-- puma
|   +-- 0987
|   |  +-- 0987_contigs.fasta
|   +-- 1029
|   |  +-- 1029_contigs.fasta
|   +-- 1234
|   |  +-- 1234_contigs.fasta
|   +-- 4567
|   |  +-- 4567_contigs.fasta

期望输出目录结构

my_project
+-- concats
|   +-- 0987/0987_concat.fasta
|   +-- 1029/1029_concat.fasta
|   +-- 1234/1234_concat.fasta
|   +-- 4567/4567_concat.fasta
|   +-- 1290/1290_concat.fasta
+-- jaguar
+-- housecat
+-- puma

现有脚本

FILENAME=$(find . -print | grep -E '[0-9]{3,4}_contigs.fasta') # this due to many many non-target files being present. I can move it into the script later just do not want to much focus on this.

for i in $FILENAME; do
  FILE=$(basename "$i" | sed 's/_contigs//g')
  DIR=concats/${FILE%.*}
  ORGANISM=$(echo $i | cut -d/ -f 2)
  mkdir -p -- "$DIR"
  cp $i "${DIR}/${ORGANISM}_${FILE}" # rename the files here
done

for d in concats/*/ ; do
    LOCI=$(echo $d | cut -d/ -f 2)
    echo $d* > ${d}${LOCI}_concat.fasta
done

提问:是否可以在执行第二个循环前直接使用类似cat的命令合并文件,从而避免复制文件的操作?

解决方案

当然可以直接用cat合并,完全不需要先复制文件到目标目录。核心思路是先按数字目录名分组收集对应文件,再直接将同组文件合并到目标路径,这样能节省磁盘空间和操作时间。

下面是改进后的脚本:

# 遍历所有目标fasta文件,按数字目录名分组合并
find . -type f -name '*_contigs.fasta' | grep -E '[0-9]{3,4}_contigs.fasta' | while read -r file; do
    # 提取数字目录名(比如从housecat/1234/1234_contigs.fasta中得到1234)
    num_dir=$(echo "$file" | awk -F '/' '{print $(NF-1)}')
    # 定义目标目录和合并后的文件名
    target_dir="concats/${num_dir}"
    target_file="${target_dir}/${num_dir}_concat.fasta"
    
    # 创建目标目录(如果不存在)
    mkdir -p "$target_dir"
    
    # 直接将当前文件追加到合并文件中
    # 可选:如果需要在合并时标注来源物种,可以先写入一行注释
    organism=$(echo "$file" | awk -F '/' '{print $2}')
    echo ">${organism}_contigs" >> "$target_file"
    cat "$file" >> "$target_file"
done

脚本说明

  • 文件定位:用find结合grep精准筛选目标文件,避免无关文件干扰。
  • 分组依据:通过awk提取文件路径中的倒数第二级目录(即数字目录名)作为分组键。
  • 直接合并:不需要复制文件,直接用cat将原文件内容追加到对应数字目录下的合并文件中。
  • 来源标注(可选):如果需要区分不同物种的序列,可以在每个物种的序列前添加一行注释(比如>housecat_contigs),方便后续查看。

注意事项

  • 如果原文件的序列头部已经包含物种信息,可以去掉echo ">${organism}_contigs" >> "$target_file"这一行。
  • 脚本中使用read -r处理文件名,避免文件名包含空格或特殊字符时出现错误。
  • 即使某个数字目录下只有一个文件,脚本也会正常生成对应的concat.fasta文件,满足需求。

内容的提问来源于stack exchange,提问作者statlerNwaldorf

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.22 10:57:41