如何按中间目录名合并多子目录下的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
相关产品推荐
相关产品推荐

