如何串联具有相同名称开头的文件?

时间:2018-12-06 13:39:02

标签: regex loops unix bioinformatics pattern-recognition

我有一个包含数百个* .fasta文件的目录,例如:

Bonobo_sp._str01_ABC784267_CDE789456.fasta
Homo_sapiens_cc21_ABC897867_CDE456789.fasta
Homo_sapiens_cc21_ABC893673_CDE753672.fasta 
Gorilla_gorilla_ghjk6789_ABC736522_CDE789456.fasta
Gorilla_gorilla_ghjk6789_ABC627190_CDE891345.fasta
Gorilla_gorilla_ghjk6789_ABC117190_CDE661345.fasta

我要串联属于同一物种的文件,因此在这种情况下为Homo_sapiens_cc21和Gorilla_gorilla_ghjk6789。

几乎每个物种都有我需要串联的不同数量的文件。

我知道我可以在unix / linux中使用一个简单的循环,例如:

    for f in thesamename.fasta; do
        cat $f >> output.fasta
    done

但是我不知道如何在循环中指定如何仅识别以相同开头的文件。对于数百个文件,手动进行完全没有意义。

有人知道我该怎么做吗?

2 个答案:

答案 0 :(得分:5)

我将假定命名的逻辑是物种是用下划线分隔的前三个单词。我还要假设文件名中没有空格。

一种可能的策略可能是获取所有物种的列表,然后将所有带有该物种/前缀的文件合并为一个文件:

for specie in $(ls *.fasta | cut -f1-3 -d_ | sort -u)
do
    cat "$specie"*.fasta > "$specie.fasta"
done

在此代码中,您列出了所有的fasta文件,削减了物种ID,并生成了唯一的物种列表。然后,您遍历此列表,并针对每个物种,将以该物种ID开头的所有文件连接到一个具有物种名称的文件中。

可以使用find并避免使用ls来编写更健壮的解决方案,但是这些解决方案比较冗长,可能不太清晰:

while IFS= read -r -d '' specie
do
    cat "$specie"*.fasta > "$specie.fasta"
done < <(find -maxdepth 1 -name "*.fasta" -print0 | cut -z -f2 -d/ | cut -z -f1-3 -d_ | sort -zu)

答案 1 :(得分:3)

如我在上面的评论中所述,如果您知道所有基本名称并且不介意显式输入它们,那么一个简单的解决方案就是

for f in Homo_sapiens_cc21_*.fasta; 
    do cat $f >> Homo_sapiens_cc21.fasta; 
done

由于不是这种情况,因此需要找到一个通用模式来对输出进行分组。从您的示例(编辑:和您的评论)中,我看起来这可能是一个单词三遍,后跟一个下划线。

假设此模式正确,则可能会满足您的要求:

for f in *.fasta; 
    do cat $f >> $(echo $f | awk -F'_' '{print $1"_"$2"_"$3".fasta"}'); 
done

说明:

  1. 列出所有*,fasta个文件
  2. 从前缀构造文件名。我们通过遍历awk,告诉它用_-F'_')分割输入并将其放回('{print $1"_"$2"_"$3".fasta"}'
  3. 来完成此操作。
  4. 最后,我们cat当前文件并将输出重定向到新构建的文件名