Answers.Body: <p>You were so close! This should do the trick:</p>
  
  <pre><code>for i in {314..727}; do 
      sed -i.bak "s/^&gt;/&gt;<span class="math-container">${i}_/" mgm4761$</span>{i}.3/*.fna
  done
  </code></pre>
  
  <p>Note that I am using <code>-i</code> which makes <code>sed</code> edit the original file. Because I use <code>-i.bak</code>, this will create a backup file with the original data. Once you are sure the command does what you need, you can delete all of these files with <code>rm */*fna.bak</code>.</p>
  
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2019-09-26T16:21:17.560Z
Answers.Text: This seems to be a step in the right direction! However, there's something about it which went weird. It does what it's supposed to, but it also duplicates the headers. Example: '>314_NS500799:83:H53J2AFXX:2:11101:11350:1048
  >314_NS500799:83:H53J2AFXX:2:11101:11350:1048
  GGGCAGTCCTTGCAGGGTGATACAGTCACCGTTTCTCTGAATGGGGAGGATCGTCCCCAAACTGTCAAGTACTACCGTTTGGCCCAGATCGTCTTTCAGAACCCGTACTCTTCACTGAATCCGCGCAAGCCGGTGCGCGACATCGTCGGCA
  >314_NS500799:83:H53J2AFXX:2:11101:2772:1050
  >314_NS500799:83:H53J2AFXX:2:11101:2772:1050
  etc'
Answers.UserDisplayName: Laura
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2019-09-26T16:31:16.147Z
Answers.Text: IMO perl -p -i -e gives you more regex power, but this problem is easily solved just anchor the match and delete to the end
Answers.UserDisplayName: M__
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2019-09-26T16:57:44.063Z
Answers.Text: @Laura argh! That's because I'm an idiot and left a debugging command I had used while testing my answer. If you've run it already, you will want to rename all the `bak` files back to the original. You can do this with: `for i in */*bak; do mv "$i" "${i//.bak}"; done`. Then, run the updated command (without the `p` at the end of the `s///`) and it should work as expected.
Answers.UserDisplayName: terdon
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2019-09-26T16:59:03.363Z
Answers.Text: @MichaelG. yes, `perl` is indeed better (and is where `sed` got the `-i` from), but overkill here. The match is already anchored to the beginning. The issue was that I had used `s/foo/bar/p` and the `p` causes `sed` to print any line where the substitution was successful. I was using that along with `-n` which suppresses output to test that it was working as expected, but forgot to remove it when posting the answer.
Answers.UserDisplayName: terdon
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2019-09-26T17:03:01.677Z
Answers.Text: @Laura if you didn't keep the backup files, you can remove the duplicated headers with `perl -i -ne 'if(/^>/ && $_ eq $last){next}; print; $last=$_; ' */*fna`.
Answers.UserDisplayName: terdon
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2019-10-01T13:49:00.167Z
Answers.Text: @MichaelG. Do you know, by any chance, how I could add a layer of complexity to this code? As in, instead of adding from a range of numbers that happen to be equivalent to folder endings, would there be a way to do this if I didn't know those numbers from before? I tried this to add codes from multiple folder names to the fasta, but...it's so bad that I'm not even getting an error message.
  `for j in ${j}; do
          for i in ${i}; do
                  sed -i.bak "s/^>/>${j}_${i}_/" mgp${j}/mgm????${i}.3/*.fna
          done
  done`
Answers.UserDisplayName: Laura
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2019-10-01T15:52:25.233Z
Answers.Text: @terdon is the expert on bash and awk. Personally I'd write a Perl script using glob, you might achieve it by piping.
Answers.UserDisplayName: M__
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2019-10-01T16:03:48.903Z
Answers.Text: Looking at your code, that is  alot  of directories why not replace ??? With *
Answers.UserDisplayName: M__
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2019-10-01T16:47:34.060Z
Answers.Text: @Laura I'm afraid I can't answer without knowing your directory names. But as Micahel said, `for dir in *` might be enough. You might want to ask a new question though where you can give us the relevant details (the devil's in the details with this sort of thing).
Answers.UserDisplayName: terdon
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2019-09-26T16:01:04.813Z
Answers.LastActivityDate: 2019-09-26T16:57:49.220Z
Answers.LastEditDate: 2019-09-26T16:57:49.220Z
Answers.UserDisplayName: terdon
Body: <p>My directories are organized as follows: one main directory, in which I have multiple directories that end with a number ranging from 314 to 727, followed by .3   . For example, 'mgm4761314.3'. Within these directories, I have fasta files named after a similar pattern (for example, mgm4761314.3.299.screen.passed.fna is in the directory mgm4761314.3).</p>
  
  <p>There is only one such file (.fna) per directory.</p>
  
  <p>What I've been trying to do is to write a loop that would go through all these folders and fasta files, and add the short number associated with the folder/file name (eg. 314, 315...727) to the headers. For example, for my first folder/fasta file, instead of:</p>
  
  <pre><code>&gt;seq1
  &gt;seq2
  </code></pre>
  
  <p>I want:</p>
  
  <pre><code>&gt;314_seq1
  &gt;314_seq2
  </code></pre>
  
  <p>The output would be exported to a file called, for instance, 314.fna.</p>
  
  <p>I've sort of made it work for one number at a time, but I have plenty of files, so I'd appreciate if anyone could help me with the loop part! This is what I tried (and it didn't work). Using ubuntu.</p>
  
  <pre><code>for i in {314..727}; do sed "s/&gt;/&gt;<span class="math-container">${i}_/" [...]/*$</span>{i}.3/mgm4761<span class="math-container">${i}.3.299.screen.passed.fna &gt; [...]/*$</span>{i}.3/${i}.fna; done
  </code></pre>
  
Comments.ContentLicense: CC BY-SA 4.0
Comments.CreationDate: 2019-09-26T15:37:48.693Z
Comments.Text: This should be easy enough, but please [edit] your question to clarify the directory structure. Does this need to be done to _all_ files with an `.fna` extension in each directory?
Comments.UserDisplayName: terdon
Comments.ContentLicense: CC BY-SA 4.0
Comments.CreationDate: 2019-09-26T15:46:13.733Z
Comments.Text: @terdon Edited! Basically, there is only one file per directory (and all files are .fna)
Comments.UserDisplayName: Laura
Comments.ContentLicense: CC BY-SA 4.0
Comments.CreationDate: 2019-09-26T16:29:30.517Z
Comments.Text: Or could go perl -p -i -e 's/
Comments.UserDisplayName: M__
Tags: <fasta><bash>
Title: How to edit the headers of multiple fasta files from multiple folders?
ThreadText: # How to edit the headers of multiple fasta files from multiple folders?
  
  (Asked by: username_0 on 2019-09-26)
  
  My directories are organized as follows: one main directory, in which I have multiple directories that end with a number ranging from 314 to 727, followed by .3 . For example, 'mgm4761314.3'. Within these directories, I have fasta files named after a similar pattern (for example, mgm4761314.3.299.screen.passed.fna is in the directory mgm4761314.3).
  
  There is only one such file (.fna) per directory.
  
  What I've been trying to do is to write a loop that would go through all these folders and fasta files, and add the short number associated with the folder/file name (eg. 314, 315...727) to the headers. For example, for my first folder/fasta file, instead of:
  
  ```
  >seq1
  >seq2
  
  ```
  
  I want:
  
  ```
  >314_seq1
  >314_seq2
  
  ```
  
  The output would be exported to a file called, for instance, 314.fna.
  
  I've sort of made it work for one number at a time, but I have plenty of files, so I'd appreciate if anyone could help me with the loop part! This is what I tried (and it didn't work). Using ubuntu.
  
  ```
  for i in {314..727}; do sed "s/>/>${i}_/" [...]/*${i}.3/mgm4761${i}.3.299.screen.passed.fna > [...]/*${i}.3/${i}.fna; done
  
  ```
  
  **Tags:** fasta, bash
  
  > **Comments:**
  > **username_1**: This should be easy enough, but please [edit] your question to clarify the directory structure. Does this need to be done to _all_ files with an `.fna` extension in each directory?  
  > **username_0**: @username_1 Edited! Basically, there is only one file per directory (and all files are .fna)  
  > **username_2**: Or could go perl -p -i -e 's/  
  
  ---
  
  ## 1 answers
  
  ### Answer by username_1 on 2019-09-26. Score: 3 | Accepted answer
  
  You were so close! This should do the trick:
  
  ```
  for i in {314..727}; do 
      sed -i.bak "s/^>/>${i}_/" mgm4761${i}.3/*.fna
  done
  
  ```
  
  Note that I am using `-i` which makes `sed` edit the original file. Because I use `-i.bak`, this will create a backup file with the original data. Once you are sure the command does what you need, you can delete all of these files with `rm */*fna.bak`.
  
  > **Comments:**
  > **username_0**: This seems to be a step in the right direction! However, there's something about it which went weird. It does what it's supposed to, but it also duplicates the headers. Example: '>314_NS500799:83:H53J2AFXX:2:11101:11350:1048 >314_NS500799:83:H53J2AFXX:2:11101:11350:1048 GGGCAGTCCTTGCAGGGTGATACAGTCACCGTTTCTCTGAATGGGGAGGATCGTCCCCAAACTGTCAAGTACTACCGTTTGGCCCAGATCGTCTTTCAGAACCCGTACTCTTCACTGAATCCGCGCAAGCCGGTGCGCGACATCGTCGGCA >314_NS500799:83:H53J2AFXX:2:11101:2772:1050 >314_NS500799:83:H53J2AFXX:2:11101:2772:1050 etc'  
  > **username_2**: IMO perl -p -i -e gives you more regex power, but this problem is easily solved just anchor the match and delete to the end  
  > **username_1**: @username_0 argh! That's because I'm an idiot and left a debugging command I had used while testing my answer. If you've run it already, you will want to rename all the `bak` files back to the original. You can do this with: `for i in */*bak; do mv "$i" "${i//.bak}"; done`. Then, run the updated command (without the `p` at the end of the `s///`) and it should work as expected.  
  > **username_1**: @MichaelG. yes, `perl` is indeed better (and is where `sed` got the `-i` from), but overkill here. The match is already anchored to the beginning. The issue was that I had used `s/foo/bar/p` and the `p` causes `sed` to print any line where the substitution was successful. I was using that along with `-n` which suppresses output to test that it was working as expected, but forgot to remove it when posting the answer.  
  > **username_1**: @username_0 if you didn't keep the backup files, you can remove the duplicated headers with `perl -i -ne 'if(/^>/ && $_ eq $last){next}; print; $last=$_; ' */*fna`.  
  > **username_0**: @MichaelG. Do you know, by any chance, how I could add a layer of complexity to this code? As in, instead of adding from a range of numbers that happen to be equivalent to folder endings, would there be a way to do this if I didn't know those numbers from before? I tried this to add codes from multiple folder names to the fasta, but...it's so bad that I'm not even getting an error message. `for j in ${j}; do         for i in ${i}; do                 sed -i.bak "s/^>/>${j}_${i}_/" mgp${j}/mgm????${i}.3/*.fna         done done`  
  > **username_2**: @username_1 is the expert on bash and awk. Personally I'd write a Perl script using glob, you might achieve it by piping.  
  > **username_2**: Looking at your code, that is  alot  of directories why not replace ??? With *  
  > **username_1**: @username_0 I'm afraid I can't answer without knowing your directory names. But as Micahel said, `for dir in *` might be enough. You might want to ask a new question though where you can give us the relevant details (the devil's in the details with this sort of thing).  
  
  ---
  
  