我有一个包含数百个* .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
但是我不知道如何在循环中指定如何仅识别以相同开头的文件。对于数百个文件,手动进行完全没有意义。
有人知道我该怎么做吗?
答案 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
说明:
*,fasta
个文件awk
,告诉它用_
(-F'_'
)分割输入并将其放回('{print $1"_"$2"_"$3".fasta"}'
)cat
当前文件并将输出重定向到新构建的文件名