Answers.Body: <p>There is a very simple <a href="http://biopython.org/" rel="noreferrer">BioPython</a> solution, that is minimal, readable, and handles multi-line fasta:</p>
  
  <pre><code>from Bio import SeqIO
  
  for record in SeqIO.parse('example.fa', 'fasta'):
      print('&gt;{}\t{}'.format(record.description, record.seq))
  </code></pre>
  
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2017-10-17T21:43:19.270Z
Answers.LastActivityDate: 2017-10-17T21:43:19.270Z
Answers.UserDisplayName: Chris_Rands
Answers.Body: <p>assuming there is only one sequence line per record, use paste with two 'stdin'</p>
  
  <pre><code>cat your.fasta | paste - -
  </code></pre>
  
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2017-10-17T12:24:56.507Z
Answers.Text: Note that this will fail if you have multi line sequences (as Pierre pointed out), but also if you have any blank lines in the file. You might also want to remove the [UuOC](http://catb.org/jargon/html/U/UUOC.html): `paste - - < file.fa`.
Answers.UserDisplayName: terdon
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2017-10-17T11:53:41.097Z
Answers.LastActivityDate: 2017-10-17T11:53:41.097Z
Answers.UserDisplayName: Pierre
Answers.Body: <p>You can use these commands:</p>
  
  <pre><code>perl -pe 's/&gt;(.*)/&gt;\1\t/g; s/\n//g; s/&gt;/\n&gt;/g' sequences.fa | grep -v '^$'
  </code></pre>
  
  <p>Explanation:</p>
  
  <ol>
  <li>Append a tab to every header line</li>
  <li>Join all lines</li>
  <li>Split the single obtained line by the '>' character</li>
  <li>Remove the empty line (the first line is empty due to the fact that '>' is the first character of the FASTA file)</li>
  </ol>
  
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2017-10-25T20:51:41.967Z
Answers.LastActivityDate: 2019-05-23T08:17:25.103Z
Answers.LastEditDate: 2019-05-23T08:17:25.103Z
Answers.UserDisplayName: Karel Břinda
Answers.Body: <p>Where possible, I recommend using a dedicated parsing library, rather than hacking a parser together: as you can see in the other answers, parsing even simple formats gets complex pretty quickly if you value correctness.</p>
  
  <p>Here’s a small R script that does what we need, using <a href="https://cran.r-project.org/package=seqinr" rel="nofollow noreferrer">‘seqinr’</a>:</p>
  
  <pre class="lang-r prettyprint-override"><code>#!/usr/bin/env Rscript
  suppressPackageStartupMessages(library(seqinr))
  parsed = read.fasta(file('stdin'), as.string = TRUE)
  table = data.frame(unlist(parsed), row.names = sapply(parsed, attr, 'Annot'))
  write.table(table, stdout(), sep = '\t', quote = FALSE, col.names = FALSE)
  </code></pre>
  
  <p>Save it as <code>fasta-to-tsv</code>, make it executable, and use it as follows:</p>
  
  <pre><code>fasta-to-tsv &lt; input.fasta &gt; output.tsv
  </code></pre>
  
  <p>Equivalent code of similar length can be written in Python or Perl.</p>
  
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2020-06-14T18:03:08.300Z
Answers.Text: Could you also explain what packages need to be installed in order for R to do this? `seqinr` isn't part of vanilla R.
Answers.UserDisplayName: terdon
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2020-06-14T18:08:44.403Z
Answers.Text: @terdon I’m slightly confused: ‘seqinr’ *is* the package name, so that’s the one to install.
Answers.UserDisplayName: Konrad Rudolph
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2020-06-14T18:26:13.553Z
Answers.Text: Well, sometimes the name of the package isn't the same as the library you load from it. And in any case, R being the horribly complicated mess that it is, you can never know (or I can't, anyway) whether the package can be installed with `install.package` or needs to be done through bioconductor or whatever else may be the case. R package management is very far from trivial, so I thought it would be useful to explain how to install the packages necessary to run your code. I've edited the command in now. I'd upvote, but I already did so back in 2017 :)
Answers.UserDisplayName: terdon
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2020-06-14T19:29:15.463Z
Answers.Text: @terdon “sometimes the name of the package isn't the same as the library you load from it” — No, for R it always is, by definition. As for installation, I’ll give you that there’s a special case for packages not on CRAN but it only really makes sense to spell out the exceptions, not the rule. You wouldn’t mention installation instructions for Perl packages on CPAN, nor for Python on PyPI, NPM for JavaScript or Rust crates. I’ve undone your edit because (a) it’s redundant, and (b) it was wrong. **Never** install packages via `sudo R` unless you’re the sysadmin maintaining a cluster.
Answers.UserDisplayName: Konrad Rudolph
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2020-06-14T23:49:46.973Z
Answers.Text: Ah, I tried it without but it failed when trying to install to my user's local library, so I assumed the package could only be installed system wide. But that just proves why it is helpful to include the installation command. I don't know R (and hate it with a passion) so all these things that you mention which are obvious to you, are not to me. And possibly others, which is why yes, I always include commands to install packages in my answers.
Answers.UserDisplayName: terdon
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2017-10-17T16:45:11.120Z
Answers.LastActivityDate: 2020-06-14T19:28:40.803Z
Answers.LastEditDate: 2020-06-14T19:28:40.803Z
Answers.UserDisplayName: Konrad Rudolph
Answers.Body: <p>This could be easily done by <a href="https://bioinf.shenwei.me/seqkit/usage/#fx2tab-tab2fx" rel="nofollow noreferrer">seqkit fx2tab</a></p>
  <pre><code>seqkit fx2tab seq.fa
  </code></pre>
  <p>However, seqkit will not print the &quot;greater than&quot; symbol (&quot;&gt;&quot;). If you do need the symbol:</p>
  <pre><code>seqkit fx2tab seq.fa | sed 's/^/&gt;/g'
  </code></pre>
  
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2022-08-26T00:38:11.723Z
Answers.LastActivityDate: 2022-08-26T00:38:11.723Z
Answers.UserDisplayName: Forrest Vigor
Answers.Body: <p>A very useful tool for this kind of data manipulation is <a href="https://github.com/lh3/bioawk" rel="noreferrer">bioawk</a>:</p>
  
  <pre><code>$ bioawk -c fastx '{print "&gt;"$name" "$comment"\t"$seq}' test.fa
  &gt;sample 1 gene 1    atgc
  &gt;sample 1 gene 2    atgc
  &gt;sample 2 gene 1    atgc
  </code></pre>
  
  <p>bioawk is based on awk, with added parsing capabilities. Here, we tell that the format is fasta or fastq with <code>-c fastx</code>, and this makes the <code>$name</code> (between ">" and the first blank character), <code>$comment</code> (after the first blank character) and <code>$seq</code> (the sequence, in one line) variables available within awk instructions.</p>
  
  <p>See for instance <a href="https://bioinformatics.stackexchange.com/a/116/292">this answer</a> for another use case.</p>
  
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2017-10-19T09:04:01.870Z
Answers.LastActivityDate: 2017-10-19T09:09:15.057Z
Answers.LastEditDate: 2017-10-19T09:09:15.057Z
Answers.UserDisplayName: bli
Answers.Body: <p>In cases where there is no sequence wrapping and each sequence occupies only a single line, the following shell command is probably going to be fastest, easiest, and most convenient.</p>
  
  <pre><code>paste - - &lt; your.fasta &gt; your.new.fasta
  </code></pre>
  
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2019-05-23T15:40:10.203Z
Answers.Text: Oops, looks like Pierre already suggested this. :-)
Answers.UserDisplayName: Daniel Standage
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2023-05-14T14:20:02.357Z
Answers.Text: You don't need to leave [duplicate answers](https://bioinformatics.stackexchange.com/a/2650/16755) lying around, you could delete it.
Answers.UserDisplayName: Ed Morton
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2019-05-23T15:39:34.233Z
Answers.LastActivityDate: 2019-05-23T15:39:34.233Z
Answers.UserDisplayName: Daniel Standage
Answers.Body: <p>Remove empty records (description without sequence):</p>
  
  <pre><code>awk '$2{print RS}$2' FS='\n' RS=\&gt; ORS= f1.fa &gt; f2.fa
  </code></pre>
  
  <p>Remove blank lines:</p>
  
  <pre><code>sed '/^$/d' f2.fa &gt; f3.fa
  </code></pre>
  
  <p>Convert multi-line fasta to single-line fasta:</p>
  
  <pre><code>awk '/^&gt;/ {printf("\n%s\n",$0);next; } { printf("%s",$0);} END {printf("\n");}' f3.fa &gt; f4.fa
  </code></pre>
  
  <p>Finally, @Pierre solution:</p>
  
  <pre><code>cat f4.fa | paste - - &gt; f.txt
  </code></pre>
  
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2017-10-17T14:20:51.570Z
Answers.LastActivityDate: 2017-10-17T14:20:51.570Z
Answers.UserDisplayName: burger
Answers.Body: <p>Just suggested improvements to the awk scripts in <a href="https://bioinformatics.stackexchange.com/a/2651/16755">@terdon's answer</a>, using any POSIX awk:</p>
  <pre><code>$ cat FastaToTbl
  #!/usr/bin/env bash
  
  awk -v OFS='\t' '
      {
          if ( /^&gt;/ ) { out = (NR&gt;1 ? ORS : &quot;&quot;) substr(<span class="math-container">$0,2) OFS }
          else        { out = $0 }
          printf "%s", out
      }
      END { print "" }
  ' "$</span>{@:--}&quot;
  </code></pre>
  <p>
  <pre><code>$ cat TblToFasta
  #!/usr/bin/env bash
  
  awk -F'\t' '
      {
          gsub(/.{60}/,&quot;&amp;&quot;ORS,<span class="math-container">$2)
          sub(ORS"$</span>&quot;,&quot;&quot;,<span class="math-container">$2)
          print "&gt;" $</span>1 ORS <span class="math-container">$2
      }
  ' "$</span>{@:--}&quot;
  </code></pre>
  <p>
  <pre><code>$ ./FastaToTbl file.fa
  sequence1       ATGCGGAGCTTAGATTCTCGAGATCTCGATATCGCGCTTATAAAAGGCCCGGATTAGGGCTAGCTAGATATCGCGATAGCTAGGGATATCGAGATGCGATACG
  sequence2       GTACTCGATACGCTACGCGATATTGCGCGATACGCATAGCTAACGATCGACTAGTGATGCATAGAGCTAGATCAGCTACGATAGCATCGATCGACTACGATCAGCATCAC
  </code></pre>
  <p>
  <pre><code>$ ./FastaToTbl file.fa | ./TblToFasta
  &gt;sequence1
  ATGCGGAGCTTAGATTCTCGAGATCTCGATATCGCGCTTATAAAAGGCCCGGATTAGGGC
  TAGCTAGATATCGCGATAGCTAGGGATATCGAGATGCGATACG
  &gt;sequence2
  GTACTCGATACGCTACGCGATATTGCGCGATACGCATAGCTAACGATCGACTAGTGATGC
  ATAGAGCTAGATCAGCTACGATAGCATCGATCGACTACGATCAGCATCAC
  </code></pre>
  <p><code>FastaToTbl</code> will actually work in any awk but <code>TblToFasta</code> requires a POSIX awk for support of regexp intervals like <code>{60}</code>. If you have a very old, pre-POSIX awk that doesn't support regexp intervals then <strong>get a new awk</strong> but if that's impossible for some reason then change <code>TblToFasta</code> to the following and then it'll also work in any awk:</p>
  <pre><code>$ cat TblToFasta
  #!/usr/bin/env bash
  
  awk -F'\t' '
      BEGIN {
          dots = sprintf(&quot;%&quot;60&quot;s&quot;,&quot;&quot;)
          gsub(/ /,&quot;.&quot;,dots)
      }
      {
          gsub(dots,&quot;&amp;&quot;ORS,<span class="math-container">$2)
          sub(ORS"$</span>&quot;,&quot;&quot;,<span class="math-container">$2)
          print "&gt;" $</span>1 ORS <span class="math-container">$2
      }
  ' "$</span>{@:--}&quot;
  </code></pre>
  
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2023-05-14T13:30:15.187Z
Answers.Text: Heh, I have been using these two scripts for decades, long before I knew the first thing about awk, and I've never bothered to go and review them. Your versions are much simpler, thanks!
Answers.UserDisplayName: terdon
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2023-05-14T14:09:46.957Z
Answers.Text: It's hard to figure out why that second one especially was so complicated. I feel like it maybe was intended to handle additional types of input, not just what's output by the first script, e.g. maybe lines which have multiple chunks of sequence string separated by spaces? That loop on field numbers but doing something specific for field numbers 1 and NF-1 (which could also be 1?) and printing every other field, then falling into a second loop that's again printing substrings of the last field is baffling.
Answers.UserDisplayName: Ed Morton
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2023-05-14T14:14:08.903Z
Answers.Text: Ohhhhhh hang on - I get it. That first loop is trying to handle a sequence name that can contain spaces because they didn't set FS to `\t`. There's obviously far more concise ways they could have done that (but if we just set FS to `\t` then we don't have to). I'm assuming sequence names can't contain tabs.
Answers.UserDisplayName: Ed Morton
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2023-05-14T13:25:43.300Z
Answers.LastActivityDate: 2023-05-14T14:00:01.083Z
Answers.LastEditDate: 2023-05-14T14:00:01.083Z
Answers.UserDisplayName: Ed Morton
Answers.Body: <p>In python I would do:</p>
  <pre><code>#...Suppose you have header information and 
  #...sequences stored in lists
  
  header_info1 = [elements]
  header_info2 = [elements]
  sequences = [sequences]
  index = enumerate(sequences)
  table = open(pathtoyourfile.tsv,'w+')
  for h1,h2,s,i in zip(header_info1,header_info2,sequences,index):
      table.write(f&quot;&gt;{h1}\t{h2}\t{s}\n&quot;)
      if i+1==len(sequences):
         table.write(f&quot;&gt;{h1}\t{h2}\t{s}&quot;)
  table.close()
  </code></pre>
  <p>So basically I use f strings and I iterate over these three vectors that are of the same length. At the end of the iteration, I remove new line(\n) since it won't be needed anymore since you have not to write anything further.</p>
  
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2022-02-28T17:13:43.363Z
Answers.Text: How is this any different / better than the other pythonic answer? This looks a lot more verbose but doing actually less than the original one (assuming data is loaded already). It could be I am just missing something, but it would be good to explain why your solution might be favorable in some cases.
Answers.UserDisplayName: Kamil S Jaron
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2022-03-21T16:37:40.883Z
Answers.Text: It is not that my solution is favorable in comparison to the other. As a developer, I found myself very often involved in situations where you have to bend the codes to my needs. Rather than understanding pre-made functions and losing time, I prefer to go on my own. Moreover, I saw that, commonly, f strings are not very well known yet, and in python-format function is used. I thought only it was a good occasion to share something that I commonly use.
Answers.UserDisplayName: Spartan 117
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2022-02-25T19:38:34.227Z
Answers.LastActivityDate: 2022-02-25T20:39:14.490Z
Answers.LastEditDate: 2022-02-25T20:39:14.490Z
Answers.UserDisplayName: Spartan 117
Answers.Body: <p>This is an old post I have noticed and there are many offered solutions. Since it’s a frequently asked question, I thought it’s worth for me to mention that there is an overlooked tool set which contains a stand-alone program called <code>faToTab</code> in addition to many other useful bioinformatics tools.</p>
  <p><code>faToTab inputFile.fasta outFileFasta_tab.txt</code></p>
  <p>It’s a gold-chest in my opinion. Here are the links to utilities folder and details:
  <a href="http://hgdownload.soe.ucsc.edu/downloads.html#source_downloads" rel="nofollow noreferrer">Description and Download instructions</a> -
  <a href="http://hgdownload.soe.ucsc.edu/admin/exe/" rel="nofollow noreferrer">Binaries by machine type</a> -
  <a href="https://github.com/ucscGenomeBrowser/kent" rel="nofollow noreferrer">Link to the github page</a>.</p>
  <p>Anaconda installation is:</p>
  <pre><code>conda install -c bioconda ucsc-fatotab
  conda install -c bioconda/label/cf201901 ucsc-fatotab
  </code></pre>
  
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2022-02-25T18:54:32.857Z
Answers.Text: Thank you. I did not know there was a conda installation. It is convenient for sure.
Answers.UserDisplayName: Supertech
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2022-02-25T18:15:19.853Z
Answers.LastActivityDate: 2022-02-25T18:23:14.580Z
Answers.LastEditDate: 2022-02-25T18:23:14.580Z
Answers.UserDisplayName: Supertech
Answers.Body: <p>If you have multi-line fasta files, as is very common, you can use these scripts<sup>1</sup> to convert between fasta and tbl (sequence_name <code>&lt;TAB&gt;</code> sequence) format:</p>
  
  <ul>
  <li><p>FastaToTbl</p>
  
  <pre class="lang-c prettyprint-override"><code>#!/usr/bin/awk -f
  {
          if (substr($1,1,1)=="&gt;")
        if (NR&gt;1)
                       printf "\n%s\t", substr($0,2,length($0)-1)
        else 
         printf "%s\t", substr($0,2,length($0)-1)
              else 
                      printf "%s", $0
  }END{printf "\n"}
  </code></pre></li>
  <li><p>TblToFasta</p>
  
  <pre class="lang-c prettyprint-override"><code>#! /usr/bin/awk -f
  {
    sequence=$NF
  
    ls = length(sequence)
    is = 1
    fld  = 1
    while (fld &lt; NF)
    {
       if (fld == 1){printf "&gt;"}
       printf "%s " , $fld
  
       if (fld == NF-1)
        {
          printf "\n"
        }
        fld = fld+1
    }
    while (is &lt;= ls)
    {
      printf "%s\n", substr(sequence,is,60)
      is=is+60
    }
  }
  </code></pre></li>
  </ul>
  
  <p>Save those in your <code>$PATH</code>, make them executable, and you can then do:</p>
  
  <pre><code>$ cat file.fa
  &gt;sequence1 
  ATGCGGAGCTTAGATTCTCGAGATCTCGATATCGCGCTTATAAAAGGCCCGGATTAGGGC
  TAGCTAGATATCGCGATAGCTAGGGATATCGAGATGCGATACG
  &gt;sequence2 
  GTACTCGATACGCTACGCGATATTGCGCGATACGCATAGCTAACGATCGACTAGTGATGC
  ATAGAGCTAGATCAGCTACGATAGCATCGATCGACTACGATCAGCATCAC
  $ FastaToTbl file.fa 
  sequence1   ATGCGGAGCTTAGATTCTCGAGATCTCGATATCGCGCTTATAAAAGGCCCGGATTAGGGCTAGCTAGATATCGCGATAGCTAGGGATATCGAGATGCGATACG
  sequence2   GTACTCGATACGCTACGCGATATTGCGCGATACGCATAGCTAACGATCGACTAGTGATGCATAGAGCTAGATCAGCTACGATAGCATCGATCGACTACGATCAGCATCAC
  </code></pre>
  
  <p>And, to get the Fasta back:</p>
  
  <pre><code>$ FastaToTbl file.fa | TblToFasta
  &gt;sequence1 
  ATGCGGAGCTTAGATTCTCGAGATCTCGATATCGCGCTTATAAAAGGCCCGGATTAGGGC
  TAGCTAGATATCGCGATAGCTAGGGATATCGAGATGCGATACG
  &gt;sequence2 
  GTACTCGATACGCTACGCGATATTGCGCGATACGCATAGCTAACGATCGACTAGTGATGC
  ATAGAGCTAGATCAGCTACGATAGCATCGATCGACTACGATCAGCATCAC
  </code></pre>
  
  <p>This can be a very useful trick when searching a fasta file for a string:</p>
  
  <pre><code>TblToFasta file.fa | grep 'foo' | FastaToTbl
  </code></pre>
  
  <hr>
  
  <p>If you really want to keep the leading <code>&gt;</code> of the header (which doesn't seem very useful), you could do something like this:</p>
  
  <pre><code>$ perl -0pe 's/\n//g; s/.&gt;/\n&gt;/g; s/$/\n/;' file.fa 
  &gt;sequence1 ATGCGGAGCTTAGATTCTCGAGATCTCGATATCGCGCTTATAAAAGGCCCGGATTAGGGCTAGCTAGATATCGCGATAGCTAGGGATATCGAGATGCGATAC
  &gt;sequence2 GTACTCGATACGCTACGCGATATTGCGCGATACGCATAGCTAACGATCGACTAGTGATGCATAGAGCTAGATCAGCTACGATAGCATCGATCGACTACGATCAGCATCAC
  </code></pre>
  
  <p>But that will read the entire file into memory. If that's an issue, add an empty line between each fasta record, and then use perl's paragraph mode to process each "paragraph" (sequence) at a time:</p>
  
  <pre><code>perl -pe  's/&gt;/\n&gt;/' file.fa | perl -00pe 's/\n//g; s/.&gt;/\n&gt;/g; s/$/\n/;'
  </code></pre>
  
  <hr>
  
  <p><sup>1</sup><sub>Credit to Josep Abril who wrote these scripts more than a decade ago.</sub></p>
  
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2023-05-14T13:26:45.297Z
Answers.Text: I added [an answer](https://bioinformatics.stackexchange.com/a/21020/16755) just to show possible improvements to the 2 awk scripts which IMHO are over-complicated with too much code duplication and other issues.
Answers.UserDisplayName: Ed Morton
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2017-10-17T12:21:47.597Z
Answers.LastActivityDate: 2018-07-09T17:20:30.093Z
Answers.LastEditDate: 2018-07-09T17:20:30.093Z
Answers.UserDisplayName: terdon
Body: <p>I have a fasta file like </p>
  
  <pre><code>&gt;sample 1 gene 1
  atgc
  &gt;sample 1 gene 2
  atgc
  &gt;sample 2 gene 1 
  atgc
  </code></pre>
  
  <p>I want to get the following output, with one break between the header and the sequence.</p>
  
  <pre><code>&gt;sample 1 gene 1   atgc
  &gt;sample 1 gene 2   atgc
  &gt;sample 2 gene 1   atgc
  </code></pre>
  
Comments.ContentLicense: CC BY-SA 3.0
Comments.CreationDate: 2017-10-18T12:29:01.243Z
Comments.Text: Thanks so much everyone. You're making it hard to choose. I wanted something for a multi line fasta so both terdon and Chris scripts are correct. So I will defer to the saying first come first served.
Comments.UserDisplayName: AudileF
Tags: <fasta><format-conversion>
Title: How to convert fasta file to tab delimited file
ThreadText: # How to convert fasta file to tab delimited file
  
  (Asked by: username_0 on 2017-10-17)
  
  I have a fasta file like
  
  ```
  >sample 1 gene 1
  atgc
  >sample 1 gene 2
  atgc
  >sample 2 gene 1 
  atgc
  
  ```
  
  I want to get the following output, with one break between the header and the sequence.
  
  ```
  >sample 1 gene 1   atgc
  >sample 1 gene 2   atgc
  >sample 2 gene 1   atgc
  
  ```
  
  **Tags:** fasta, format-conversion
  
  > **Comments:**
  > **username_0**: Thanks so much everyone. You're making it hard to choose. I wanted something for a multi line fasta so both username_3 and Chris scripts are correct. So I will defer to the saying first come first served.  
  
  ---
  
  ## 12 answers
  
  ### Answer by username_3 on 2017-10-17. Score: 13 | Accepted answer
  
  If you have multi-line fasta files, as is very common, you can use these scripts1 to convert between fasta and tbl (sequence\_name `<TAB>` sequence) format:
  
  * FastaToTbl
  
    ```c
    #!/usr/bin/awk -f
    {
            if (substr($1,1,1)==">")
          if (NR>1)
                         printf "\n%s\t", substr($0,2,length($0)-1)
          else 
           printf "%s\t", substr($0,2,length($0)-1)
                else 
                        printf "%s", $0
    }END{printf "\n"}
  
    ```
  * TblToFasta
  
    ```c
    #! /usr/bin/awk -f
    {
      sequence=$NF
  
      ls = length(sequence)
      is = 1
      fld  = 1
      while (fld < NF)
      {
         if (fld == 1){printf ">"}
         printf "%s " , $fld
  
         if (fld == NF-1)
          {
            printf "\n"
          }
          fld = fld+1
      }
      while (is <= ls)
      {
        printf "%s\n", substr(sequence,is,60)
        is=is+60
      }
    }
  
    ```
  
  Save those in your `$PATH`, make them executable, and you can then do:
  
  ```
  $ cat file.fa
  >sequence1 
  ATGCGGAGCTTAGATTCTCGAGATCTCGATATCGCGCTTATAAAAGGCCCGGATTAGGGC
  TAGCTAGATATCGCGATAGCTAGGGATATCGAGATGCGATACG
  >sequence2 
  GTACTCGATACGCTACGCGATATTGCGCGATACGCATAGCTAACGATCGACTAGTGATGC
  ATAGAGCTAGATCAGCTACGATAGCATCGATCGACTACGATCAGCATCAC
  $ FastaToTbl file.fa 
  sequence1   ATGCGGAGCTTAGATTCTCGAGATCTCGATATCGCGCTTATAAAAGGCCCGGATTAGGGCTAGCTAGATATCGCGATAGCTAGGGATATCGAGATGCGATACG
  sequence2   GTACTCGATACGCTACGCGATATTGCGCGATACGCATAGCTAACGATCGACTAGTGATGCATAGAGCTAGATCAGCTACGATAGCATCGATCGACTACGATCAGCATCAC
  
  ```
  
  And, to get the Fasta back:
  
  ```
  $ FastaToTbl file.fa | TblToFasta
  >sequence1 
  ATGCGGAGCTTAGATTCTCGAGATCTCGATATCGCGCTTATAAAAGGCCCGGATTAGGGC
  TAGCTAGATATCGCGATAGCTAGGGATATCGAGATGCGATACG
  >sequence2 
  GTACTCGATACGCTACGCGATATTGCGCGATACGCATAGCTAACGATCGACTAGTGATGC
  ATAGAGCTAGATCAGCTACGATAGCATCGATCGACTACGATCAGCATCAC
  
  ```
  
  This can be a very useful trick when searching a fasta file for a string:
  
  ```
  TblToFasta file.fa | grep 'foo' | FastaToTbl
  
  ```
  
  ---
  
  If you really want to keep the leading `>` of the header (which doesn't seem very useful), you could do something like this:
  
  ```
  $ perl -0pe 's/\n//g; s/.>/\n>/g; s/$/\n/;' file.fa 
  >sequence1 ATGCGGAGCTTAGATTCTCGAGATCTCGATATCGCGCTTATAAAAGGCCCGGATTAGGGCTAGCTAGATATCGCGATAGCTAGGGATATCGAGATGCGATAC
  >sequence2 GTACTCGATACGCTACGCGATATTGCGCGATACGCATAGCTAACGATCGACTAGTGATGCATAGAGCTAGATCAGCTACGATAGCATCGATCGACTACGATCAGCATCAC
  
  ```
  
  But that will read the entire file into memory. If that's an issue, add an empty line between each fasta record, and then use perl's paragraph mode to process each "paragraph" (sequence) at a time:
  
  ```
  perl -pe  's/>/\n>/' file.fa | perl -00pe 's/\n//g; s/.>/\n>/g; s/$/\n/;'
  
  ```
  
  ---
  
  1Credit to Josep Abril who wrote these scripts more than a decade ago.
  
  > **Comments:**
  > **username_9**: I added [an answer](https://bioinformatics.stackexchange.com/a/21020/16755) just to show possible improvements to the 2 awk scripts which IMHO are over-complicated with too much code duplication and other issues.  
  
  ---
  
  ### Answer by username_1 on 2017-10-17. Score: 12
  
  There is a very simple [BioPython](http://biopython.org/) solution, that is minimal, readable, and handles multi-line fasta:
  
  ```
  from Bio import SeqIO
  
  for record in SeqIO.parse('example.fa', 'fasta'):
      print('>{}\t{}'.format(record.description, record.seq))
  
  ```
  
  
  ---
  
  ### Answer by username_2 on 2017-10-17. Score: 9
  
  assuming there is only one sequence line per record, use paste with two 'stdin'
  
  ```
  cat your.fasta | paste - -
  
  ```
  
  > **Comments:**
  > **username_3**: Note that this will fail if you have multi line sequences (as username_2 pointed out), but also if you have any blank lines in the file. You might also want to remove the [UuOC](http://catb.org/jargon/html/U/UUOC.html): `paste - - < file.fa`.  
  
  ---
  
  ### Answer by username_4 on 2017-10-25. Score: 8
  
  You can use these commands:
  
  ```
  perl -pe 's/>(.*)/>\1\t/g; s/\n//g; s/>/\n>/g' sequences.fa | grep -v '^$'
  
  ```
  
  Explanation:
  
  1. Append a tab to every header line
  2. Join all lines
  3. Split the single obtained line by the '>' character
  4. Remove the empty line (the first line is empty due to the fact that '>' is the first character of the FASTA file)
  
  
  ---
  
  ### Answer by username_7 on 2017-10-19. Score: 7
  
  A very useful tool for this kind of data manipulation is [bioawk](https://github.com/lh3/bioawk):
  
  ```
  $ bioawk -c fastx '{print ">"$name" "$comment"\t"$seq}' test.fa
  >sample 1 gene 1    atgc
  >sample 1 gene 2    atgc
  >sample 2 gene 1    atgc
  
  ```
  
  bioawk is based on awk, with added parsing capabilities. Here, we tell that the format is fasta or fastq with `-c fastx`, and this makes the `$name` (between ">" and the first blank character), `$comment` (after the first blank character) and `$seq` (the sequence, in one line) variables available within awk instructions.
  
  See for instance [this answer](https://bioinformatics.stackexchange.com/a/116/292) for another use case.
  
  
  ---
  
  ### Answer by username_5 on 2017-10-17. Score: 4
  
  Where possible, I recommend using a dedicated parsing library, rather than hacking a parser together: as you can see in the other answers, parsing even simple formats gets complex pretty quickly if you value correctness.
  
  Here’s a small R script that does what we need, using [‘seqinr’](https://cran.r-project.org/package=seqinr):
  
  ```r
  #!/usr/bin/env Rscript
  suppressPackageStartupMessages(library(seqinr))
  parsed = read.fasta(file('stdin'), as.string = TRUE)
  table = data.frame(unlist(parsed), row.names = sapply(parsed, attr, 'Annot'))
  write.table(table, stdout(), sep = '\t', quote = FALSE, col.names = FALSE)
  
  ```
  
  Save it as `fasta-to-tsv`, make it executable, and use it as follows:
  
  ```
  fasta-to-tsv < input.fasta > output.tsv
  
  ```
  
  Equivalent code of similar length can be written in Python or Perl.
  
  > **Comments:**
  > **username_3**: Could you also explain what packages need to be installed in order for R to do this? `seqinr` isn't part of vanilla R.  
  > **username_5**: @username_3 I’m slightly confused: ‘seqinr’ *is* the package name, so that’s the one to install.  
  > **username_3**: Well, sometimes the name of the package isn't the same as the library you load from it. And in any case, R being the horribly complicated mess that it is, you can never know (or I can't, anyway) whether the package can be installed with `install.package` or needs to be done through bioconductor or whatever else may be the case. R package management is very far from trivial, so I thought it would be useful to explain how to install the packages necessary to run your code. I've edited the command in now. I'd upvote, but I already did so back in 2017 :)  
  > **username_5**: @username_3 “sometimes the name of the package isn't the same as the library you load from it” — No, for R it always is, by definition. As for installation, I’ll give you that there’s a special case for packages not on CRAN but it only really makes sense to spell out the exceptions, not the rule. You wouldn’t mention installation instructions for Perl packages on CPAN, nor for Python on PyPI, NPM for JavaScript or Rust crates. I’ve undone your edit because (a) it’s redundant, and (b) it was wrong. **Never** install packages via `sudo R` unless you’re the sysadmin maintaining a cluster.  
  > **username_3**: Ah, I tried it without but it failed when trying to install to my user's local library, so I assumed the package could only be installed system wide. But that just proves why it is helpful to include the installation command. I don't know R (and hate it with a passion) so all these things that you mention which are obvious to you, are not to me. And possibly others, which is why yes, I always include commands to install packages in my answers.  
  
  ---
  
  ### Answer by username_6 on 2022-08-26. Score: 3
  
  This could be easily done by [seqkit fx2tab](https://bioinf.shenwei.me/seqkit/usage/#fx2tab-tab2fx)
  
  ```
  seqkit fx2tab seq.fa
  
  ```
  
  However, seqkit will not print the "greater than" symbol (">"). If you do need the symbol:
  
  ```
  seqkit fx2tab seq.fa | sed 's/^/>/g'
  
  ```
  
  
  ---
  
  ### Answer by username_8 on 2019-05-23. Score: 2
  
  In cases where there is no sequence wrapping and each sequence occupies only a single line, the following shell command is probably going to be fastest, easiest, and most convenient.
  
  ```
  paste - - < your.fasta > your.new.fasta
  
  ```
  
  > **Comments:**
  > **username_8**: Oops, looks like username_2 already suggested this. :-)  
  > **username_9**: You don't need to leave [duplicate answers](https://bioinformatics.stackexchange.com/a/2650/16755) lying around, you could delete it.  
  
  ---
  
  ### Answer by username_10 on 2017-10-17. Score: 2
  
  Remove empty records (description without sequence):
  
  ```
  awk '$2{print RS}$2' FS='\n' RS=\> ORS= f1.fa > f2.fa
  
  ```
  
  Remove blank lines:
  
  ```
  sed '/^$/d' f2.fa > f3.fa
  
  ```
  
  Convert multi-line fasta to single-line fasta:
  
  ```
  awk '/^>/ {printf("\n%s\n",$0);next; } { printf("%s",$0);} END {printf("\n");}' f3.fa > f4.fa
  
  ```
  
  Finally, @username_2 solution:
  
  ```
  cat f4.fa | paste - - > f.txt
  
  ```
  
  
  ---
  
  ### Answer by username_9 on 2023-05-14. Score: 2
  
  Just suggested improvements to the awk scripts in [@username_3's answer](https://bioinformatics.stackexchange.com/a/2651/16755), using any POSIX awk:
  
  ```
  $ cat FastaToTbl
  #!/usr/bin/env bash
  
  awk -v OFS='\t' '
      {
          if ( /^>/ ) { out = (NR>1 ? ORS : "") substr($0,2) OFS }
          else        { out = $0 }
          printf "%s", out
      }
      END { print "" }
  ' "${@:--}"
  
  ```
  
  ```
  $ cat TblToFasta
  #!/usr/bin/env bash
  
  awk -F'\t' '
      {
          gsub(/.{60}/,"&"ORS,$2)
          sub(ORS"$","",$2)
          print ">" $1 ORS $2
      }
  ' "${@:--}"
  
  ```
  
  ```
  $ ./FastaToTbl file.fa
  sequence1       ATGCGGAGCTTAGATTCTCGAGATCTCGATATCGCGCTTATAAAAGGCCCGGATTAGGGCTAGCTAGATATCGCGATAGCTAGGGATATCGAGATGCGATACG
  sequence2       GTACTCGATACGCTACGCGATATTGCGCGATACGCATAGCTAACGATCGACTAGTGATGCATAGAGCTAGATCAGCTACGATAGCATCGATCGACTACGATCAGCATCAC
  
  ```
  
  ```
  $ ./FastaToTbl file.fa | ./TblToFasta
  >sequence1
  ATGCGGAGCTTAGATTCTCGAGATCTCGATATCGCGCTTATAAAAGGCCCGGATTAGGGC
  TAGCTAGATATCGCGATAGCTAGGGATATCGAGATGCGATACG
  >sequence2
  GTACTCGATACGCTACGCGATATTGCGCGATACGCATAGCTAACGATCGACTAGTGATGC
  ATAGAGCTAGATCAGCTACGATAGCATCGATCGACTACGATCAGCATCAC
  
  ```
  
  `FastaToTbl` will actually work in any awk but `TblToFasta` requires a POSIX awk for support of regexp intervals like `{60}`. If you have a very old, pre-POSIX awk that doesn't support regexp intervals then **get a new awk** but if that's impossible for some reason then change `TblToFasta` to the following and then it'll also work in any awk:
  
  ```
  $ cat TblToFasta
  #!/usr/bin/env bash
  
  awk -F'\t' '
      BEGIN {
          dots = sprintf("%"60"s","")
          gsub(/ /,".",dots)
      }
      {
          gsub(dots,"&"ORS,$2)
          sub(ORS"$","",$2)
          print ">" $1 ORS $2
      }
  ' "${@:--}"
  
  ```
  
  > **Comments:**
  > **username_3**: Heh, I have been using these two scripts for decades, long before I knew the first thing about awk, and I've never bothered to go and review them. Your versions are much simpler, thanks!  
  > **username_9**: It's hard to figure out why that second one especially was so complicated. I feel like it maybe was intended to handle additional types of input, not just what's output by the first script, e.g. maybe lines which have multiple chunks of sequence string separated by spaces? That loop on field numbers but doing something specific for field numbers 1 and NF-1 (which could also be 1?) and printing every other field, then falling into a second loop that's again printing substrings of the last field is baffling.  
  > **username_9**: Ohhhhhh hang on - I get it. That first loop is trying to handle a sequence name that can contain spaces because they didn't set FS to `\t`. There's obviously far more concise ways they could have done that (but if we just set FS to `\t` then we don't have to). I'm assuming sequence names can't contain tabs.  
  
  ---
  
  ### Answer by username_11 on 2022-02-25. Score: 1
  
  In python I would do:
  
  ```
  #...Suppose you have header information and 
  #...sequences stored in lists
  
  header_info1 = [elements]
  header_info2 = [elements]
  sequences = [sequences]
  index = enumerate(sequences)
  table = open(pathtoyourfile.tsv,'w+')
  for h1,h2,s,i in zip(header_info1,header_info2,sequences,index):
      table.write(f">{h1}\t{h2}\t{s}\n")
      if i+1==len(sequences):
         table.write(f">{h1}\t{h2}\t{s}")
  table.close()
  
  ```
  
  So basically I use f strings and I iterate over these three vectors that are of the same length. At the end of the iteration, I remove new line(\n) since it won't be needed anymore since you have not to write anything further.
  
  > **Comments:**
  > **username_12**: How is this any different / better than the other pythonic answer? This looks a lot more verbose but doing actually less than the original one (assuming data is loaded already). It could be I am just missing something, but it would be good to explain why your solution might be favorable in some cases.  
  > **username_11**: It is not that my solution is favorable in comparison to the other. As a developer, I found myself very often involved in situations where you have to bend the codes to my needs. Rather than understanding pre-made functions and losing time, I prefer to go on my own. Moreover, I saw that, commonly, f strings are not very well known yet, and in python-format function is used. I thought only it was a good occasion to share something that I commonly use.  
  
  ---
  
  ### Answer by username_13 on 2022-02-25. Score: 1
  
  This is an old post I have noticed and there are many offered solutions. Since it’s a frequently asked question, I thought it’s worth for me to mention that there is an overlooked tool set which contains a stand-alone program called `faToTab` in addition to many other useful bioinformatics tools.
  
  `faToTab inputFile.fasta outFileFasta_tab.txt`
  
  It’s a gold-chest in my opinion. Here are the links to utilities folder and details:
  [Description and Download instructions](http://hgdownload.soe.ucsc.edu/downloads.html#source_downloads) -
  [Binaries by machine type](http://hgdownload.soe.ucsc.edu/admin/exe/) -
  [Link to the github page](https://github.com/ucscGenomeBrowser/kent).
  
  Anaconda installation is:
  
  ```
  conda install -c bioconda ucsc-fatotab
  conda install -c bioconda/label/cf201901 ucsc-fatotab
  
  ```
  
  > **Comments:**
  > **username_13**: Thank you. I did not know there was a conda installation. It is convenient for sure.  
  
  ---
  
  