如何将多个文件中的行复制到一个新文件中并保留文件名?

如何将多个文件中的行复制到一个新文件中并保留文件名?

我有 81 个 .fasta 格式的文件,其中包含(最多)53 个项目。例如:

/User/MyData/Sample_1.fasta
/User/MyData/Sample_2.fasta
....
/User/MyData/Sample_81.fasta

每个 .fasta 文件包含一个名称 ID 和分隔如下的字符串:

>AT1G00001
ATCCACTGCTGTGTACCTGATCAGTGCTGACCCAYTGTGACACTGTG
>AT2G00002
AAAAATTTTGCCCGTGTGGGCCAAACTGTCATGCATGCACCGTACGTGCATGCAT
....
>ATXGXXXXX(up to 53)
AAACCCTCTTTGTGCCTGTGCATGCA

我想将 81 个 .fasta 文件中的每个字符串复制到一个新的 .fasta 文件中,以便:

/User/MyData/AT1G00001.fasta
/User/MyData/AT2G00002.fasta
....
/User/MyData/ATXGXXXXX.fasta

其中之一的内容包含(从目录中的所有“Sample_X.fasta”文件复制后):

>Sample_1
ATCCACTGCTGTGTACCTGATCAGTGCTGACCCAYTGTGACACTGTG
>Sample_2
ATCGACTCCCGTAGGACTGATTTTTCTGACCCCATTGTGACACTGTG
....
>Sample_81
TTCTGACCCCATTGTGACACTGTGATCGACTCCCGTAGGACTGATTT

我遇到过一两个类似的问题,但与在复制的输出文件中保留 SampleName 的细微差别没有什么区别,并且我在从类似但不同的问题中获取示例时遇到一些困难。

非常感谢您的帮助!

答案1

我为您准备了以下代码;下面有一个解释它是如何工作的。

首先进入工作目录(cd /User/MyData/)运行该程序:

awk '
  FNR==1 { sample = FILENAME ; sub(/\.fasta/, "", sample }
  /^>/   { target = substr($0,2)".fasta" ; next }
         { print ">" sample > target ; print > target }
' Sample_*.fasta

awk程序迭代所有Sample_*.fasta文件。在每个输入文件 ( ) 的开头,FNR==1它通过删除后缀“.fasta”从当前文件名中提取样本名称。如果一行以 开头,>则该记录的目标文件名取自该>字符之后,并附加文件名后缀“.fasta”。对于其他类型的行,先前提取的样本名称将写入目标文件,并在第二行中写入当前数据。

注意:如果您发现“打开文件描述符太多”的问题,那么最好的选择是切换到 GNU(awk如果可能)!

如果 GNUawk没有或不能在您的平台上可用,那么您需要进行一些额外的更改;关键是使用该函数在写入每个文件后关闭每个文件close(),结果是您必须附加到已关闭的文件。 (这更复杂,性能也较差,因此值得考虑获取 GNUawk并使用第一个变体。)

这些更改将产生如下程序:

# because of the append operation you need to empty the file targets
# before calling subsequent awk code, e.g. by: rm -f AT???????.fasta
awk '
  FNR==1 { sample = FILENAME ; sub(/\.fasta/, "", sample }
  /^>/   { target = substr($0,2)".fasta" ; next }
         { printf ">%s\n%s\n", sample, %0 >> target ; close(target) }
' Sample_*.fasta

请注意,在调用该awk程序之前,您必须确保从先前的调用中删除或清空任何现有的输出文件(否则您的新输出将被附加到先前存在于相应输出文件中的数据中。

答案2

尽管了解您到目前为止所尝试过的内容会很有趣,但这里有一个如何awk用于这项工作的示例:

awk '
    FNR == 1 {
        sub(/\.fasta$/, "", FILENAME)
    }
    /^>/ && sub(/^>/, "") {
        newfile = $0 ".fasta"
        next
    }
    {
        print ">" FILENAME >> newfile
        print $0 >> newfile
    }' Sample_*.fasta

答案3

一些 shell:这会比 awk 程序慢得多。

cd /User/MyData
for sample in Sample*.fasta; do
    sample_name=${sample%.fasta}
    while read name; read data; do
        name=${name#>}
        printf ">%s\n%s\n" "$sample_name" "$data" >> "$name.fasta"
    done < "$sample"
done

相关内容