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):


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:


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

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"
| improve this answer | |
  • Worked like a charm. I didnt test the other solutions, but thank you anyway. – nouse Mar 8 '17 at 12:03

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
| improve this answer | |

This should work for bash:

for filename in *.fasta; do
  sed "s/^>/>$addme-/g" "$filename" > "$addme"_tagged.fasta

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

| improve this answer | |
  • 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
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"


 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-/" 
| improve this answer | |
  • 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

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.