3

I have text-files containing many lines, of which some starts with ">" (it's a so-called *.fasta file, and the ">"s marks the beginning of a new information container):

>header_name1
sequence_info
>header_name2
sequence_info

I want to add the name of the file these lines are located in to the header. For example, if the file is named "1_nc.fasta", all the lines inside the file starting with > should have the label "001" added:

>001-header_name1
sequence_info
>001-header_name2
sequence_info

Someone nice provided me with this line:

sed 's/^>/>001-/g' 1_nc.fasta>001_tagged.fasta 

Accordingly, all headers in 2_nc.fasta should start with "002-", 3_nc.fasta -> "003-", and so on.

I know how to write parallel job scripts, but the jobs are done so quickly, I think a script that serially processes all files in a loop is much better. Unfortunately, I can't do this on my own.

Added twist: 11_nc.fasta and 149_nc.fasta are not available.

How can I loop that through all the 500 files in my directory?

  • 4
    Note that the /g there is useless and only serves, if it serves at all, to make your command slower. – terdon Mar 7 '17 at 18:56
5

This should do the trick. I break the filename at the underscore to get the numerical prefix, and then use a printf to zero-pad it out to a three digit string.

for file in *.fasta; do
    prefix="$(printf "%03d" "${file%%_*}")"
    sed  "s/^>/>$prefix-/" "$file" > "${prefix}_tagged.fasta"
done 
  • Worked like a charm. I didnt test the other solutions, but thank you anyway. – nouse Mar 8 '17 at 12:03
3

This seems to do it

for f in *.fasta ; do echo sed "s/^>/>$(printf %03d "${f%%_*}")-/" "$f"; done

Test it as above for a preview, then remove echo to see what the contents will be:

for f in *.fasta ; do sed "s/^>/>$(printf %03d "${f%%_*}"-)/" "$f"; done

To make the new files, add redirection

for f in * ; do sed "s/^>/>$(printf %03d "${f%%_*}")/" "$f" > "$(printf %03d "${f%%_*}")_tagged.fasta"; done
2
for n in 000{0..999}; do
   M=${n#???} N=${n##${n%???}}
   [ -f "${M}_nc.fasta" ] && sed -e "s/^>/&$N-/" < "${M}_nc.fasta" > "${N}_tagged.fasta"
done

Summary

 n varies from 0000 -> 000999
 M varies from    0 ->    999 strip off the first 3 chars ${n#???}
 N is computed by removing the last 3 chars from n then what remains
   is then stripped , essentially performing the act of padding to 3 digits.

compute the filenames:
   fasda filename = ${M}_nc.fasta <------ input file to sed
   new filename   = ${N}_tagged.fasta <---- output file from sed

   sed command:   "s/^>/&$N-/" 
  • A word of explanation would be in order here. I can't tell what you're trying to do with your parameter expansion, because what you've used doesn't make sense. – Wildcard Mar 8 '17 at 5:21
2

This should work for bash:

for filename in *.fasta; do
  index="00${filename%_*}"
  addme="${index:((-3)):3}"
  sed "s/^>/>$addme-/g" "$filename" > "$addme"_tagged.fasta
done

The trick was to expand the index to three-digit. Then you need " instead of ' to allow for expansion of $addme

  • you are absolutely correct, I had misunderstood. Downvote converted to an upvote. Sorry! I deleted our previous exchange since I wasn't saying anything useful and you were just answering my nonsense. – terdon Mar 9 '17 at 10:34
  • @Zanna I feel I should put the record straight. Philippos was absolutely right and I was absolutely wrong. – terdon Mar 9 '17 at 10:34

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.