Как переименовать заголовки во многих многофастовых файлах с именем файла?

У меня есть каталог с несколькими сотнями файлов multi-FASTA. Эти файлы называются по названию вида или рода, например:

Bubo_bubo.fasta
Poa_CC7849.fasta
Homo_sapiens.fasta
...

Внутри каждого файла заголовки автоматически генерируются ассемблером Trinity и выглядят примерно так:

>c5_g1_i1 len=168 path=[174:0-148 24:148-168]

Я хотел бы переименовать заголовки в каждом из этих файлов, добавив информацию о видах, из которых он исходит. Другими словами, заголовок должен содержать в начале имя файла. Например, если заголовок выше исходит от Bubo_bubo.fasta, он должен выглядеть так:

>Bubu_bubo_c5_g1_i1 len=168 path=[174:0-148 24:148-168]

Итак, я хочу написать цикл, который будет принимать имя файла и использовать его для добавления этой информации в каждый заголовок fasta в этом конкретном файле, и я хочу сделать это для всех файлов в каталоге.


person magda_wu    schedule 10.12.2018    source источник
comment
поле len в вашем заголовке относится к длине файла? в этом случае ваш заголовок может быть неправильным, когда вы его меняете.   -  person 1010    schedule 10.12.2018
comment
@1010 это файл FASTA со словом header, OP относится к строке, которая начинается с > в начале строки. Содержимое строки может быть любым. В каждом файле будет несколько заголовков. Строки, следующие за заголовком, обычно представляют собой последовательность символов, представляющих некоторые биологические данные.   -  person kvantour    schedule 10.12.2018


Ответы (1)


Следующее должно помочь вам:

awk '(FNR==1){f=FILENAME;sub(/\.[A-Za-z]*$/,"_",f)}
     /^>/{$0=">" f substr($0,2)}
     1' Bubo_bubo.fasta

Это, однако, запишет все на экран, вместо этого вам могут быть интересны новые файлы. Таким образом, вы можете использовать bash с перенаправлением для нескольких файлов как:

for f in *.fasta; do
   awk '(FNR==1){f=FILENAME;sub(/\.[A-Za-z]*$/,"_",f)}
        /^>/{$0=">" f substr($0,2)}
        1' "$f" > "/path/to/new/location/$(basename $f)"
done

Если очень хочется, то можно все сделать в самом awk, а это будет:

awk '(FNR==1){                             # When a new file is opened (first record)
        close(fout);                       # close previous output file
        fout=FILENAME
        sub(".*/", "", fout)               # get basename of file
        f=fout                             # set f to basename of file
        fout="path/to/new/location/" fout  # prepend output directory
        sub(/\.[A-Za-z]*$/,"_",f)          # remove extention from f
     }
     /^>/{$0=">" f substr($0,2)}           # if header found, update it
     {print > fout}                        # print to output file
    ' *.fasta
person kvantour    schedule 10.12.2018
comment
Привет @kvantour! Спасибо за помощь! И как я мог указать какой-либо файл фаста? Просто так? awk '(FNR==1){f=FILENAME;sub(/\.[A-Za-z]*$/,"_",f)} /^>/{$0=">" f substr($0,2)} 1' *.fasta - person magda_wu; 10.12.2018
comment
@magda_wu да. Но таким образом он выведет что угодно на экран. Возможно, установлено мягкое обновление. всего секунду. - person kvantour; 10.12.2018
comment
@magda_wu Я добавил обновление, которое создаст файлы порядка Bubo_bubo.fasta.new. Пожалуйста, сначала протестируйте сценарий, прежде чем запускать его со всеми своими данными. Возможно, он не делает то, что вы ожидаете. Тем не менее, я предполагаю, что это так. - person kvantour; 10.12.2018
comment
Я должен признать, что у меня есть некоторые проблемы с пониманием этой команды. Не могли бы вы помочь мне с этим? Могу ли я указать другой каталог для записи вывода, просто заменив {print > fout} на {print > ./anotherdir/fout} ? - person magda_wu; 10.12.2018
comment
@magda_wu Я немного обновил ответ, надеюсь, это объяснит вам. - person kvantour; 10.12.2018
comment
Вау! спасибо за наше обновление @kvantour! Ваше объяснение действительно очень помогло! - person magda_wu; 10.12.2018