This is an expansion of my previous question, How to edit the headers of multiple fasta files from multiple folders?

My directories are organized as follows: one main directory, in which I have multiple project directories. Inside each project directory, there are multiple metagenome directories. Inside each metagenome directory, there is always a single .fna (fasta) file.

Names: project directories start with 'mgp', metagenome directories start with 'mgm' and end with '.3'. They end in numbers, but the numbers are not related. (eg. project directory 'mgp83581' contains metagenome directory 'mgm4729322.3').

What I want is a loop that would go through all these fasta files, and add to the headers codes corresponding to project and metagenome directory. For example, if the fasta file in project directory mgp83581, metagenome subdirectory mgm4729322.3 had the following headers...



...then I would want to change it to:



Basically, I want to add the number code associated with the project, and the last three digits of the 7-digit code associated with the metagenome (apart from the '.3' part of the file name).

Below is the answer that I got for my previous question, where I didn't have project directories, and where the 3-digit code for the metagenomes stayed in a manageable range. (thanks terdon!)

for i in {314..727}; do sed -i.bak "s/^>/>${i}_/" mgm4761${i}.3/*.fna done

Using ubuntu. I would appreciate your help!


1 Answer 1


You can edit your for loop so as to include the paths to your files of interest.

The command below will give you the relative paths (relative to where you run the command, I think it is better to run this within your main directory) of your files of interest:

ls mpg*/mgm*.3/*.fna

You can use the output of this command (your files of interest) to iterate over via your for loop. Your code will look like:

for i in {...}; do 
    sed -i.bak "s/^>/>${i}_/" i
  • $\begingroup$ Alot slicker than using Perl $\endgroup$
    – M__
    Oct 2, 2019 at 19:49
  • $\begingroup$ Thank you! I've tried to do this. (though tried 'while' instead) ls mgp*/mgm*.3/*.fna | while read line ; do header=$(sed -r "s/^mgp([0-9]*)\/mgm[0-9]{4}([0-9]{1,})\.3\/(mgm.*\.fna)/\1_\2/") sed -i.bak "s/^>/>${header}_/" $line done It seems to only edit the first of the files I'm interested in (but it does it correctly as far as I can tell). Any idea of what could've gone wrong? $\endgroup$
    – Laura
    Oct 3, 2019 at 10:45
  • $\begingroup$ I am not sure if you really need that complicated command within do, fasta headers always start with >, which seems to be parsed in your sed. My suggestion would be: ls mgp*/mgm*.3/*.fna | while read line; do sed -i.bak "s/^>/>${i}_/" $line; done. $\endgroup$
    – haci
    Oct 3, 2019 at 12:24
  • $\begingroup$ I've tried. For some reason it doesn't work for me. All it does is add an underscore to the fasta headers in the edited files. $\endgroup$
    – Laura
    Oct 7, 2019 at 12:01
  • $\begingroup$ It is because I forgot to change the ${i} part in sed while editing the code regarding your comment above with while read. You can do something like ${line:Ind:Len}, Ind being the zero based index and Len is the length of the substring you would like to extract from the full file path. $\endgroup$
    – haci
    Oct 7, 2019 at 13:38

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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