How to redirect stdout to a file, and stdout+stderr to another one?Show only stderr on screen but write both stdout and stderr to fileAppend output to a file and redirect stderr to nullRedirect stderr and stdout to another file descriptorRedirect script stderr & stdout to a file, but keep stdout to tty as well?bash: redirect stderr to file and stdout + stderr to screenRedirect bash stdout+stderr to one file and stderr to another fileAppend stderr and stdout to filestdout and stderr redirection to different files

Does immunity to fear prevent a mummy's Dreadful Glare from paralyzing a character?

Word for 'most late'

How does a ball bearing door hinge work?

Which culture used no personal names?

What's that funny "illo" I keep hearing in Southern Spain?

Encountering former, abusive advisor at a conference

How does an alien race from a dying world annihilate most of humanity to colonize the planet for themselves?

If we should encrypt the message rather than the method of transfer, why do we care about wifi security? Is this just security theatre?

What's the meaning of java.util.@Nullable?

Did Terry Pratchett ever explain the inspiration behind the Luggage?

Christmas party at employers home

Is is possible to externally power my DSLR with the original battery that is connected to the DSLR by means of wires?

How to figure out key from key signature?

How can you tell apart the pronounciation at the end between the "meine" and "meiner" in the daily spoken situation?

Does my protagonist need to be the most important character?

Do more Americans want the Bidens investigated than Trump impeached?

Where is the circle of fifths mentioned for the first time?

Company indirectly discriminating against introverts, specifically INTJ

Does a quantum computer have a clock signal and if yes how big is it?

How to increment the value of a (decimal) variable (with leading zero) by +1?

Moonlight bright enough to see by

Code Golf Measurer © 2019

How (and if) to include name change for transgender person in genealogy?

Get injured / Get increased



How to redirect stdout to a file, and stdout+stderr to another one?


Show only stderr on screen but write both stdout and stderr to fileAppend output to a file and redirect stderr to nullRedirect stderr and stdout to another file descriptorRedirect script stderr & stdout to a file, but keep stdout to tty as well?bash: redirect stderr to file and stdout + stderr to screenRedirect bash stdout+stderr to one file and stderr to another fileAppend stderr and stdout to filestdout and stderr redirection to different files






.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty
margin-bottom:0;









32

















How can I achieve



cmd >> file1 2>&1 1>>file2


That is, the stdout and stderr should redirect to one file (file1) and only stdout (file2) should redirect to another (both in append mode)?










share|improve this question



































    32

















    How can I achieve



    cmd >> file1 2>&1 1>>file2


    That is, the stdout and stderr should redirect to one file (file1) and only stdout (file2) should redirect to another (both in append mode)?










    share|improve this question































      32












      32








      32


      3






      How can I achieve



      cmd >> file1 2>&1 1>>file2


      That is, the stdout and stderr should redirect to one file (file1) and only stdout (file2) should redirect to another (both in append mode)?










      share|improve this question

















      How can I achieve



      cmd >> file1 2>&1 1>>file2


      That is, the stdout and stderr should redirect to one file (file1) and only stdout (file2) should redirect to another (both in append mode)?







      shell io-redirection io stdout stderr






      share|improve this question
















      share|improve this question













      share|improve this question




      share|improve this question








      edited May 15 at 5:23









      Scott

      7,6525 gold badges30 silver badges54 bronze badges




      7,6525 gold badges30 silver badges54 bronze badges










      asked May 13 at 10:38









      Swarna GowriSwarna Gowri

      3052 silver badges7 bronze badges




      3052 silver badges7 bronze badges























          5 Answers
          5






          active

          oldest

          votes


















          41


















          Problem is that when you redirect your output, it's not available anymore for the next redirect. You can pipe to tee in a subshell to keep the output for the second redirection:



          ( cmd | tee -a file2 ) >> file1 2>&1


          or if you like to see the output in terminal:



          ( cmd | tee -a file2 ) 2>&1 | tee -a file1



          To avoid adding the stderr of the first tee to file1, you should redirect the stderr of your command to some file descriptor (e.g. 3), and later add this to stdout again:



          ( 2>&3 cmd | tee -a file2 ) >> file1 3>&1
          # or
          ( 2>&3 cmd | tee -a file2 ) 3>&1 | tee -a file1


          (thanks @fra-san)






          share|improve this answer



































            16


















            With zsh:



            cmd >& out+err.log > out.log


            In append mode:



            cmd >>& out+err.log >> out.log


            In zsh, and provided the mult_ios option has not been disabled, when a file descriptor (here 1) is redirected several times for writing, then the shell implements a built-in tee to duplicate the output to all targets.






            share|improve this answer




























            • I can't figure out what out+err and out mean here. File names? Streams to be redirected?

              – gronostaj
              May 13 at 20:27











            • @gronostaj Think that the command reads cmd >& file1 > file2

              – Isaac
              May 13 at 22:00












            • This solution will preserve the order in which the output was generated. To actually store the stdout and stderr (in that order) you need a different approach.

              – Isaac
              May 13 at 22:02






            • 1





              @Isaac, the order will not necessarily be preserved as the stdout output will go through a pipe (to a process that forwards it to each file) while the stderr output will go directly to the file. In any case, it doesn't look like the OP asked for the stderr output to come after the stdout one.

              – Stéphane Chazelas
              May 14 at 11:07


















            3


















            You could : tag stdout (using an UNBUFFERED sed, ie: sed -u ...), have stderr also go to stdout (untagged, as it didn't go through that tagging sed), and thus be able to differentiate the 2 in the resulting logfile.



            The following: is slow (It can be seriously optimized, by using for exemple a perl script instead of the while ... ; do ... ;done, for exemple, that will spawning subshells & commands at every lines!), weird (it seems I need the 2 stages to in one rename stdout and then in the other one add the "falled through" stderr to it), etc. But it is : a "proof of concept", that will try to keep the output's order the most of stdout & stderr as much as possible:



            #basic principle (some un-necessary "" to visually help see the layers):
            # sed -e "s/^/TAGstdout/" ; 2>&1 | read_stdin_and_redispatch

            #exemple:
            # complex command = a (slowed) ls of several things (some existing, others not)
            # to see if the order of stdout&stderr is kept

            #preparation, not needed for the "proof of concept", but needed for our specific exemple setup:
            rm out.file out_AND_err.file unknown unknown2
            touch existing existing2 existing3

            #and the (slow, too many execs, etc) "proof of concept":
            uniquetag="_stdout_" # change this to something unique, that will NOT appear in all the commands outputs...
            # avoid regexp characters ("+" "?" "*" etc) to make it easy to remove with another sed later on.

            sed -u -e "s/^/$uniquetag/" ;
            2>&1 | while IFS="" read -r line ; do
            case "$line" in
            $uniquetag*) printf "%sn" "$line" | tee -a out_AND_err.file | sed -e "s/^$uniquetag//" >> out.file ;;
            *) printf "%sn" "$line" >> out_AND_err.file ;;
            esac;
            done;

            # see the results:
            grep "^" out.file out_AND_err.file





            share|improve this answer




























            • This is really difficult to understand. (1) Why do you use such complicated use case (ls unknown) to print something on stderr? >&2 echo "error" would be fine. (2) tee can append to multiple files at once. (3) Why not just cat instead of grep "^" ? (4) your script will fail when stderr output begins with _stdout_. (5) Why?

              – pLumo
              May 13 at 13:39












            • @RoVo : the first 2 commented lines shows the algorithm, simpler than the proof of concept example. 1) : this ls loop will both output on stdout and stderr, mixed (alternatively), in a controlled order,;so that we can check we kept that stderr/stdout ordering despite the tagging of stdout 2) : gnu tail, maybe, but not regular tail (ex, on aix.). 3) : grep "^" also shows both filenames. 4) : this can be changed by the variable. 5) : the convoluted exemple works on old oses (ex, old aix) where I tested it (no perl available).

              – Olivier Dulac
              May 13 at 13:48












            • (1) multiple echo to stderr and stout would be fine, but okay, not important, would just be easier to read. (3) agree, (4) sure, but it will fail if it starts with whatever the variable contains. (5) I see.

              – pLumo
              May 13 at 13:51












            • @RoVo I agree with your 1). for 4), the variable could be as complex as needed to make the pb disappear (ex: uniquetag="banaNa11F453355B28E1158D4E516A2D3EDF96B3450406 ... )

              – Olivier Dulac
              May 13 at 13:54






            • 1





              Sure sure, it's not very likely, but anyways it might introduce a security issue later on. And then you might want to remove that string before printing to file ;-)

              – pLumo
              May 13 at 13:55



















            2


















            If order of output must be: stdout then stderr; there is no solution with redirection only.

            The stderr must be stored to a temporal file



            cmd 2>>file-err | tee -a file1 >>file2
            cat file-err >> file1
            rm file-err


            Description:



            The only way to redirect one output (an fd like stdout or stderr) to two files is to reproduce it. The command tee is the correct tool to reproduce a file descriptor content. So, an initial idea to have one output on two files would be to use:



            ... | tee file1 file2


            That reproduces the stdin of tee to both files (1 & 2) leaving the output of tee still unused. But we need to append (use -a) and only need one copy. This solve both issues:



            ... | tee -a file1 >>file2


            To supply tee with stdout (the one to repeat) we need to consume stderr directly out of the command. One way, if order is not important (order of output will (most probably) be preserved as generated, whichever is output first will be stored first). Either:



            1. cmd 2>>file1 | tee -a file2 >>file1

            2. cmd 2>>file1 > >( tee -a file2 >>file1 )

            3. ( cmd | tee -a file2 ) >> file1 2>&1

            Option 2 works only in some shells. Option 3 uses an additional subshell (slower) but use the file names only once.



            But if stdout must be first (whichever order output is generated) we need to store stderr to append it to file at the end (first solution posted).






            share|improve this answer























            • 1





              Or store in memory like sponge does: (cmd | tee -a out >> out+err) 2>&1 | sponge >> out+err

              – Stéphane Chazelas
              May 14 at 11:15


















            1


















            In the interests of diversity:



            If your system supports /dev/stderr, then



            (cmd | tee -a /dev/stderr) 2>> file1 >> file2


            will work. 
            The standard output of the cmd
            is sent to both the stdout and the stderr of the pipeline.
            The standard error of the cmd bypasses the tee
            and comes out the stderr of the pipeline.



            So



            • the stdout of the pipeline is just the stdout of the cmd, and

            • the stderr of the pipeline is the stdout and stderr of the cmd,
              intermixed.

            It's then a simple matter of sending those streams to the correct files.



            As with almost any approach like this (including Stéphane’s answer),
            file1 may get lines out of order.






            share|improve this answer



























              Your Answer








              StackExchange.ready(function()
              var channelOptions =
              tags: "".split(" "),
              id: "106"
              ;
              initTagRenderer("".split(" "), "".split(" "), channelOptions);

              StackExchange.using("externalEditor", function()
              // Have to fire editor after snippets, if snippets enabled
              if (StackExchange.settings.snippets.snippetsEnabled)
              StackExchange.using("snippets", function()
              createEditor();
              );

              else
              createEditor();

              );

              function createEditor()
              StackExchange.prepareEditor(
              heartbeatType: 'answer',
              autoActivateHeartbeat: false,
              convertImagesToLinks: false,
              noModals: true,
              showLowRepImageUploadWarning: true,
              reputationToPostImages: null,
              bindNavPrevention: true,
              postfix: "",
              imageUploader:
              brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
              contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/4.0/"u003ecc by-sa 4.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
              allowUrls: true
              ,
              onDemand: true,
              discardSelector: ".discard-answer"
              ,immediatelyShowMarkdownHelp:true
              );



              );














              draft saved

              draft discarded
















              StackExchange.ready(
              function ()
              StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2funix.stackexchange.com%2fquestions%2f518655%2fhow-to-redirect-stdout-to-a-file-and-stdoutstderr-to-another-one%23new-answer', 'question_page');

              );

              Post as a guest















              Required, but never shown


























              5 Answers
              5






              active

              oldest

              votes








              5 Answers
              5






              active

              oldest

              votes









              active

              oldest

              votes






              active

              oldest

              votes









              41


















              Problem is that when you redirect your output, it's not available anymore for the next redirect. You can pipe to tee in a subshell to keep the output for the second redirection:



              ( cmd | tee -a file2 ) >> file1 2>&1


              or if you like to see the output in terminal:



              ( cmd | tee -a file2 ) 2>&1 | tee -a file1



              To avoid adding the stderr of the first tee to file1, you should redirect the stderr of your command to some file descriptor (e.g. 3), and later add this to stdout again:



              ( 2>&3 cmd | tee -a file2 ) >> file1 3>&1
              # or
              ( 2>&3 cmd | tee -a file2 ) 3>&1 | tee -a file1


              (thanks @fra-san)






              share|improve this answer
































                41


















                Problem is that when you redirect your output, it's not available anymore for the next redirect. You can pipe to tee in a subshell to keep the output for the second redirection:



                ( cmd | tee -a file2 ) >> file1 2>&1


                or if you like to see the output in terminal:



                ( cmd | tee -a file2 ) 2>&1 | tee -a file1



                To avoid adding the stderr of the first tee to file1, you should redirect the stderr of your command to some file descriptor (e.g. 3), and later add this to stdout again:



                ( 2>&3 cmd | tee -a file2 ) >> file1 3>&1
                # or
                ( 2>&3 cmd | tee -a file2 ) 3>&1 | tee -a file1


                (thanks @fra-san)






                share|improve this answer






























                  41














                  41










                  41









                  Problem is that when you redirect your output, it's not available anymore for the next redirect. You can pipe to tee in a subshell to keep the output for the second redirection:



                  ( cmd | tee -a file2 ) >> file1 2>&1


                  or if you like to see the output in terminal:



                  ( cmd | tee -a file2 ) 2>&1 | tee -a file1



                  To avoid adding the stderr of the first tee to file1, you should redirect the stderr of your command to some file descriptor (e.g. 3), and later add this to stdout again:



                  ( 2>&3 cmd | tee -a file2 ) >> file1 3>&1
                  # or
                  ( 2>&3 cmd | tee -a file2 ) 3>&1 | tee -a file1


                  (thanks @fra-san)






                  share|improve this answer
















                  Problem is that when you redirect your output, it's not available anymore for the next redirect. You can pipe to tee in a subshell to keep the output for the second redirection:



                  ( cmd | tee -a file2 ) >> file1 2>&1


                  or if you like to see the output in terminal:



                  ( cmd | tee -a file2 ) 2>&1 | tee -a file1



                  To avoid adding the stderr of the first tee to file1, you should redirect the stderr of your command to some file descriptor (e.g. 3), and later add this to stdout again:



                  ( 2>&3 cmd | tee -a file2 ) >> file1 3>&1
                  # or
                  ( 2>&3 cmd | tee -a file2 ) 3>&1 | tee -a file1


                  (thanks @fra-san)







                  share|improve this answer















                  share|improve this answer




                  share|improve this answer








                  edited May 13 at 14:20

























                  answered May 13 at 11:20









                  pLumopLumo

                  7,93115 silver badges36 bronze badges




                  7,93115 silver badges36 bronze badges


























                      16


















                      With zsh:



                      cmd >& out+err.log > out.log


                      In append mode:



                      cmd >>& out+err.log >> out.log


                      In zsh, and provided the mult_ios option has not been disabled, when a file descriptor (here 1) is redirected several times for writing, then the shell implements a built-in tee to duplicate the output to all targets.






                      share|improve this answer




























                      • I can't figure out what out+err and out mean here. File names? Streams to be redirected?

                        – gronostaj
                        May 13 at 20:27











                      • @gronostaj Think that the command reads cmd >& file1 > file2

                        – Isaac
                        May 13 at 22:00












                      • This solution will preserve the order in which the output was generated. To actually store the stdout and stderr (in that order) you need a different approach.

                        – Isaac
                        May 13 at 22:02






                      • 1





                        @Isaac, the order will not necessarily be preserved as the stdout output will go through a pipe (to a process that forwards it to each file) while the stderr output will go directly to the file. In any case, it doesn't look like the OP asked for the stderr output to come after the stdout one.

                        – Stéphane Chazelas
                        May 14 at 11:07















                      16


















                      With zsh:



                      cmd >& out+err.log > out.log


                      In append mode:



                      cmd >>& out+err.log >> out.log


                      In zsh, and provided the mult_ios option has not been disabled, when a file descriptor (here 1) is redirected several times for writing, then the shell implements a built-in tee to duplicate the output to all targets.






                      share|improve this answer




























                      • I can't figure out what out+err and out mean here. File names? Streams to be redirected?

                        – gronostaj
                        May 13 at 20:27











                      • @gronostaj Think that the command reads cmd >& file1 > file2

                        – Isaac
                        May 13 at 22:00












                      • This solution will preserve the order in which the output was generated. To actually store the stdout and stderr (in that order) you need a different approach.

                        – Isaac
                        May 13 at 22:02






                      • 1





                        @Isaac, the order will not necessarily be preserved as the stdout output will go through a pipe (to a process that forwards it to each file) while the stderr output will go directly to the file. In any case, it doesn't look like the OP asked for the stderr output to come after the stdout one.

                        – Stéphane Chazelas
                        May 14 at 11:07













                      16














                      16










                      16









                      With zsh:



                      cmd >& out+err.log > out.log


                      In append mode:



                      cmd >>& out+err.log >> out.log


                      In zsh, and provided the mult_ios option has not been disabled, when a file descriptor (here 1) is redirected several times for writing, then the shell implements a built-in tee to duplicate the output to all targets.






                      share|improve this answer
















                      With zsh:



                      cmd >& out+err.log > out.log


                      In append mode:



                      cmd >>& out+err.log >> out.log


                      In zsh, and provided the mult_ios option has not been disabled, when a file descriptor (here 1) is redirected several times for writing, then the shell implements a built-in tee to duplicate the output to all targets.







                      share|improve this answer















                      share|improve this answer




                      share|improve this answer








                      edited May 14 at 11:08

























                      answered May 13 at 14:50









                      Stéphane ChazelasStéphane Chazelas

                      337k58 gold badges661 silver badges1038 bronze badges




                      337k58 gold badges661 silver badges1038 bronze badges















                      • I can't figure out what out+err and out mean here. File names? Streams to be redirected?

                        – gronostaj
                        May 13 at 20:27











                      • @gronostaj Think that the command reads cmd >& file1 > file2

                        – Isaac
                        May 13 at 22:00












                      • This solution will preserve the order in which the output was generated. To actually store the stdout and stderr (in that order) you need a different approach.

                        – Isaac
                        May 13 at 22:02






                      • 1





                        @Isaac, the order will not necessarily be preserved as the stdout output will go through a pipe (to a process that forwards it to each file) while the stderr output will go directly to the file. In any case, it doesn't look like the OP asked for the stderr output to come after the stdout one.

                        – Stéphane Chazelas
                        May 14 at 11:07

















                      • I can't figure out what out+err and out mean here. File names? Streams to be redirected?

                        – gronostaj
                        May 13 at 20:27











                      • @gronostaj Think that the command reads cmd >& file1 > file2

                        – Isaac
                        May 13 at 22:00












                      • This solution will preserve the order in which the output was generated. To actually store the stdout and stderr (in that order) you need a different approach.

                        – Isaac
                        May 13 at 22:02






                      • 1





                        @Isaac, the order will not necessarily be preserved as the stdout output will go through a pipe (to a process that forwards it to each file) while the stderr output will go directly to the file. In any case, it doesn't look like the OP asked for the stderr output to come after the stdout one.

                        – Stéphane Chazelas
                        May 14 at 11:07
















                      I can't figure out what out+err and out mean here. File names? Streams to be redirected?

                      – gronostaj
                      May 13 at 20:27





                      I can't figure out what out+err and out mean here. File names? Streams to be redirected?

                      – gronostaj
                      May 13 at 20:27













                      @gronostaj Think that the command reads cmd >& file1 > file2

                      – Isaac
                      May 13 at 22:00






                      @gronostaj Think that the command reads cmd >& file1 > file2

                      – Isaac
                      May 13 at 22:00














                      This solution will preserve the order in which the output was generated. To actually store the stdout and stderr (in that order) you need a different approach.

                      – Isaac
                      May 13 at 22:02





                      This solution will preserve the order in which the output was generated. To actually store the stdout and stderr (in that order) you need a different approach.

                      – Isaac
                      May 13 at 22:02




                      1




                      1





                      @Isaac, the order will not necessarily be preserved as the stdout output will go through a pipe (to a process that forwards it to each file) while the stderr output will go directly to the file. In any case, it doesn't look like the OP asked for the stderr output to come after the stdout one.

                      – Stéphane Chazelas
                      May 14 at 11:07





                      @Isaac, the order will not necessarily be preserved as the stdout output will go through a pipe (to a process that forwards it to each file) while the stderr output will go directly to the file. In any case, it doesn't look like the OP asked for the stderr output to come after the stdout one.

                      – Stéphane Chazelas
                      May 14 at 11:07











                      3


















                      You could : tag stdout (using an UNBUFFERED sed, ie: sed -u ...), have stderr also go to stdout (untagged, as it didn't go through that tagging sed), and thus be able to differentiate the 2 in the resulting logfile.



                      The following: is slow (It can be seriously optimized, by using for exemple a perl script instead of the while ... ; do ... ;done, for exemple, that will spawning subshells & commands at every lines!), weird (it seems I need the 2 stages to in one rename stdout and then in the other one add the "falled through" stderr to it), etc. But it is : a "proof of concept", that will try to keep the output's order the most of stdout & stderr as much as possible:



                      #basic principle (some un-necessary "" to visually help see the layers):
                      # sed -e "s/^/TAGstdout/" ; 2>&1 | read_stdin_and_redispatch

                      #exemple:
                      # complex command = a (slowed) ls of several things (some existing, others not)
                      # to see if the order of stdout&stderr is kept

                      #preparation, not needed for the "proof of concept", but needed for our specific exemple setup:
                      rm out.file out_AND_err.file unknown unknown2
                      touch existing existing2 existing3

                      #and the (slow, too many execs, etc) "proof of concept":
                      uniquetag="_stdout_" # change this to something unique, that will NOT appear in all the commands outputs...
                      # avoid regexp characters ("+" "?" "*" etc) to make it easy to remove with another sed later on.

                      sed -u -e "s/^/$uniquetag/" ;
                      2>&1 | while IFS="" read -r line ; do
                      case "$line" in
                      $uniquetag*) printf "%sn" "$line" | tee -a out_AND_err.file | sed -e "s/^$uniquetag//" >> out.file ;;
                      *) printf "%sn" "$line" >> out_AND_err.file ;;
                      esac;
                      done;

                      # see the results:
                      grep "^" out.file out_AND_err.file





                      share|improve this answer




























                      • This is really difficult to understand. (1) Why do you use such complicated use case (ls unknown) to print something on stderr? >&2 echo "error" would be fine. (2) tee can append to multiple files at once. (3) Why not just cat instead of grep "^" ? (4) your script will fail when stderr output begins with _stdout_. (5) Why?

                        – pLumo
                        May 13 at 13:39












                      • @RoVo : the first 2 commented lines shows the algorithm, simpler than the proof of concept example. 1) : this ls loop will both output on stdout and stderr, mixed (alternatively), in a controlled order,;so that we can check we kept that stderr/stdout ordering despite the tagging of stdout 2) : gnu tail, maybe, but not regular tail (ex, on aix.). 3) : grep "^" also shows both filenames. 4) : this can be changed by the variable. 5) : the convoluted exemple works on old oses (ex, old aix) where I tested it (no perl available).

                        – Olivier Dulac
                        May 13 at 13:48












                      • (1) multiple echo to stderr and stout would be fine, but okay, not important, would just be easier to read. (3) agree, (4) sure, but it will fail if it starts with whatever the variable contains. (5) I see.

                        – pLumo
                        May 13 at 13:51












                      • @RoVo I agree with your 1). for 4), the variable could be as complex as needed to make the pb disappear (ex: uniquetag="banaNa11F453355B28E1158D4E516A2D3EDF96B3450406 ... )

                        – Olivier Dulac
                        May 13 at 13:54






                      • 1





                        Sure sure, it's not very likely, but anyways it might introduce a security issue later on. And then you might want to remove that string before printing to file ;-)

                        – pLumo
                        May 13 at 13:55
















                      3


















                      You could : tag stdout (using an UNBUFFERED sed, ie: sed -u ...), have stderr also go to stdout (untagged, as it didn't go through that tagging sed), and thus be able to differentiate the 2 in the resulting logfile.



                      The following: is slow (It can be seriously optimized, by using for exemple a perl script instead of the while ... ; do ... ;done, for exemple, that will spawning subshells & commands at every lines!), weird (it seems I need the 2 stages to in one rename stdout and then in the other one add the "falled through" stderr to it), etc. But it is : a "proof of concept", that will try to keep the output's order the most of stdout & stderr as much as possible:



                      #basic principle (some un-necessary "" to visually help see the layers):
                      # sed -e "s/^/TAGstdout/" ; 2>&1 | read_stdin_and_redispatch

                      #exemple:
                      # complex command = a (slowed) ls of several things (some existing, others not)
                      # to see if the order of stdout&stderr is kept

                      #preparation, not needed for the "proof of concept", but needed for our specific exemple setup:
                      rm out.file out_AND_err.file unknown unknown2
                      touch existing existing2 existing3

                      #and the (slow, too many execs, etc) "proof of concept":
                      uniquetag="_stdout_" # change this to something unique, that will NOT appear in all the commands outputs...
                      # avoid regexp characters ("+" "?" "*" etc) to make it easy to remove with another sed later on.

                      sed -u -e "s/^/$uniquetag/" ;
                      2>&1 | while IFS="" read -r line ; do
                      case "$line" in
                      $uniquetag*) printf "%sn" "$line" | tee -a out_AND_err.file | sed -e "s/^$uniquetag//" >> out.file ;;
                      *) printf "%sn" "$line" >> out_AND_err.file ;;
                      esac;
                      done;

                      # see the results:
                      grep "^" out.file out_AND_err.file





                      share|improve this answer




























                      • This is really difficult to understand. (1) Why do you use such complicated use case (ls unknown) to print something on stderr? >&2 echo "error" would be fine. (2) tee can append to multiple files at once. (3) Why not just cat instead of grep "^" ? (4) your script will fail when stderr output begins with _stdout_. (5) Why?

                        – pLumo
                        May 13 at 13:39












                      • @RoVo : the first 2 commented lines shows the algorithm, simpler than the proof of concept example. 1) : this ls loop will both output on stdout and stderr, mixed (alternatively), in a controlled order,;so that we can check we kept that stderr/stdout ordering despite the tagging of stdout 2) : gnu tail, maybe, but not regular tail (ex, on aix.). 3) : grep "^" also shows both filenames. 4) : this can be changed by the variable. 5) : the convoluted exemple works on old oses (ex, old aix) where I tested it (no perl available).

                        – Olivier Dulac
                        May 13 at 13:48












                      • (1) multiple echo to stderr and stout would be fine, but okay, not important, would just be easier to read. (3) agree, (4) sure, but it will fail if it starts with whatever the variable contains. (5) I see.

                        – pLumo
                        May 13 at 13:51












                      • @RoVo I agree with your 1). for 4), the variable could be as complex as needed to make the pb disappear (ex: uniquetag="banaNa11F453355B28E1158D4E516A2D3EDF96B3450406 ... )

                        – Olivier Dulac
                        May 13 at 13:54






                      • 1





                        Sure sure, it's not very likely, but anyways it might introduce a security issue later on. And then you might want to remove that string before printing to file ;-)

                        – pLumo
                        May 13 at 13:55














                      3














                      3










                      3









                      You could : tag stdout (using an UNBUFFERED sed, ie: sed -u ...), have stderr also go to stdout (untagged, as it didn't go through that tagging sed), and thus be able to differentiate the 2 in the resulting logfile.



                      The following: is slow (It can be seriously optimized, by using for exemple a perl script instead of the while ... ; do ... ;done, for exemple, that will spawning subshells & commands at every lines!), weird (it seems I need the 2 stages to in one rename stdout and then in the other one add the "falled through" stderr to it), etc. But it is : a "proof of concept", that will try to keep the output's order the most of stdout & stderr as much as possible:



                      #basic principle (some un-necessary "" to visually help see the layers):
                      # sed -e "s/^/TAGstdout/" ; 2>&1 | read_stdin_and_redispatch

                      #exemple:
                      # complex command = a (slowed) ls of several things (some existing, others not)
                      # to see if the order of stdout&stderr is kept

                      #preparation, not needed for the "proof of concept", but needed for our specific exemple setup:
                      rm out.file out_AND_err.file unknown unknown2
                      touch existing existing2 existing3

                      #and the (slow, too many execs, etc) "proof of concept":
                      uniquetag="_stdout_" # change this to something unique, that will NOT appear in all the commands outputs...
                      # avoid regexp characters ("+" "?" "*" etc) to make it easy to remove with another sed later on.

                      sed -u -e "s/^/$uniquetag/" ;
                      2>&1 | while IFS="" read -r line ; do
                      case "$line" in
                      $uniquetag*) printf "%sn" "$line" | tee -a out_AND_err.file | sed -e "s/^$uniquetag//" >> out.file ;;
                      *) printf "%sn" "$line" >> out_AND_err.file ;;
                      esac;
                      done;

                      # see the results:
                      grep "^" out.file out_AND_err.file





                      share|improve this answer
















                      You could : tag stdout (using an UNBUFFERED sed, ie: sed -u ...), have stderr also go to stdout (untagged, as it didn't go through that tagging sed), and thus be able to differentiate the 2 in the resulting logfile.



                      The following: is slow (It can be seriously optimized, by using for exemple a perl script instead of the while ... ; do ... ;done, for exemple, that will spawning subshells & commands at every lines!), weird (it seems I need the 2 stages to in one rename stdout and then in the other one add the "falled through" stderr to it), etc. But it is : a "proof of concept", that will try to keep the output's order the most of stdout & stderr as much as possible:



                      #basic principle (some un-necessary "" to visually help see the layers):
                      # sed -e "s/^/TAGstdout/" ; 2>&1 | read_stdin_and_redispatch

                      #exemple:
                      # complex command = a (slowed) ls of several things (some existing, others not)
                      # to see if the order of stdout&stderr is kept

                      #preparation, not needed for the "proof of concept", but needed for our specific exemple setup:
                      rm out.file out_AND_err.file unknown unknown2
                      touch existing existing2 existing3

                      #and the (slow, too many execs, etc) "proof of concept":
                      uniquetag="_stdout_" # change this to something unique, that will NOT appear in all the commands outputs...
                      # avoid regexp characters ("+" "?" "*" etc) to make it easy to remove with another sed later on.

                      sed -u -e "s/^/$uniquetag/" ;
                      2>&1 | while IFS="" read -r line ; do
                      case "$line" in
                      $uniquetag*) printf "%sn" "$line" | tee -a out_AND_err.file | sed -e "s/^$uniquetag//" >> out.file ;;
                      *) printf "%sn" "$line" >> out_AND_err.file ;;
                      esac;
                      done;

                      # see the results:
                      grep "^" out.file out_AND_err.file






                      share|improve this answer















                      share|improve this answer




                      share|improve this answer








                      edited May 13 at 13:57

























                      answered May 13 at 13:23









                      Olivier DulacOlivier Dulac

                      3,99313 silver badges25 bronze badges




                      3,99313 silver badges25 bronze badges















                      • This is really difficult to understand. (1) Why do you use such complicated use case (ls unknown) to print something on stderr? >&2 echo "error" would be fine. (2) tee can append to multiple files at once. (3) Why not just cat instead of grep "^" ? (4) your script will fail when stderr output begins with _stdout_. (5) Why?

                        – pLumo
                        May 13 at 13:39












                      • @RoVo : the first 2 commented lines shows the algorithm, simpler than the proof of concept example. 1) : this ls loop will both output on stdout and stderr, mixed (alternatively), in a controlled order,;so that we can check we kept that stderr/stdout ordering despite the tagging of stdout 2) : gnu tail, maybe, but not regular tail (ex, on aix.). 3) : grep "^" also shows both filenames. 4) : this can be changed by the variable. 5) : the convoluted exemple works on old oses (ex, old aix) where I tested it (no perl available).

                        – Olivier Dulac
                        May 13 at 13:48












                      • (1) multiple echo to stderr and stout would be fine, but okay, not important, would just be easier to read. (3) agree, (4) sure, but it will fail if it starts with whatever the variable contains. (5) I see.

                        – pLumo
                        May 13 at 13:51












                      • @RoVo I agree with your 1). for 4), the variable could be as complex as needed to make the pb disappear (ex: uniquetag="banaNa11F453355B28E1158D4E516A2D3EDF96B3450406 ... )

                        – Olivier Dulac
                        May 13 at 13:54






                      • 1





                        Sure sure, it's not very likely, but anyways it might introduce a security issue later on. And then you might want to remove that string before printing to file ;-)

                        – pLumo
                        May 13 at 13:55


















                      • This is really difficult to understand. (1) Why do you use such complicated use case (ls unknown) to print something on stderr? >&2 echo "error" would be fine. (2) tee can append to multiple files at once. (3) Why not just cat instead of grep "^" ? (4) your script will fail when stderr output begins with _stdout_. (5) Why?

                        – pLumo
                        May 13 at 13:39












                      • @RoVo : the first 2 commented lines shows the algorithm, simpler than the proof of concept example. 1) : this ls loop will both output on stdout and stderr, mixed (alternatively), in a controlled order,;so that we can check we kept that stderr/stdout ordering despite the tagging of stdout 2) : gnu tail, maybe, but not regular tail (ex, on aix.). 3) : grep "^" also shows both filenames. 4) : this can be changed by the variable. 5) : the convoluted exemple works on old oses (ex, old aix) where I tested it (no perl available).

                        – Olivier Dulac
                        May 13 at 13:48












                      • (1) multiple echo to stderr and stout would be fine, but okay, not important, would just be easier to read. (3) agree, (4) sure, but it will fail if it starts with whatever the variable contains. (5) I see.

                        – pLumo
                        May 13 at 13:51












                      • @RoVo I agree with your 1). for 4), the variable could be as complex as needed to make the pb disappear (ex: uniquetag="banaNa11F453355B28E1158D4E516A2D3EDF96B3450406 ... )

                        – Olivier Dulac
                        May 13 at 13:54






                      • 1





                        Sure sure, it's not very likely, but anyways it might introduce a security issue later on. And then you might want to remove that string before printing to file ;-)

                        – pLumo
                        May 13 at 13:55

















                      This is really difficult to understand. (1) Why do you use such complicated use case (ls unknown) to print something on stderr? >&2 echo "error" would be fine. (2) tee can append to multiple files at once. (3) Why not just cat instead of grep "^" ? (4) your script will fail when stderr output begins with _stdout_. (5) Why?

                      – pLumo
                      May 13 at 13:39






                      This is really difficult to understand. (1) Why do you use such complicated use case (ls unknown) to print something on stderr? >&2 echo "error" would be fine. (2) tee can append to multiple files at once. (3) Why not just cat instead of grep "^" ? (4) your script will fail when stderr output begins with _stdout_. (5) Why?

                      – pLumo
                      May 13 at 13:39














                      @RoVo : the first 2 commented lines shows the algorithm, simpler than the proof of concept example. 1) : this ls loop will both output on stdout and stderr, mixed (alternatively), in a controlled order,;so that we can check we kept that stderr/stdout ordering despite the tagging of stdout 2) : gnu tail, maybe, but not regular tail (ex, on aix.). 3) : grep "^" also shows both filenames. 4) : this can be changed by the variable. 5) : the convoluted exemple works on old oses (ex, old aix) where I tested it (no perl available).

                      – Olivier Dulac
                      May 13 at 13:48






                      @RoVo : the first 2 commented lines shows the algorithm, simpler than the proof of concept example. 1) : this ls loop will both output on stdout and stderr, mixed (alternatively), in a controlled order,;so that we can check we kept that stderr/stdout ordering despite the tagging of stdout 2) : gnu tail, maybe, but not regular tail (ex, on aix.). 3) : grep "^" also shows both filenames. 4) : this can be changed by the variable. 5) : the convoluted exemple works on old oses (ex, old aix) where I tested it (no perl available).

                      – Olivier Dulac
                      May 13 at 13:48














                      (1) multiple echo to stderr and stout would be fine, but okay, not important, would just be easier to read. (3) agree, (4) sure, but it will fail if it starts with whatever the variable contains. (5) I see.

                      – pLumo
                      May 13 at 13:51






                      (1) multiple echo to stderr and stout would be fine, but okay, not important, would just be easier to read. (3) agree, (4) sure, but it will fail if it starts with whatever the variable contains. (5) I see.

                      – pLumo
                      May 13 at 13:51














                      @RoVo I agree with your 1). for 4), the variable could be as complex as needed to make the pb disappear (ex: uniquetag="banaNa11F453355B28E1158D4E516A2D3EDF96B3450406 ... )

                      – Olivier Dulac
                      May 13 at 13:54





                      @RoVo I agree with your 1). for 4), the variable could be as complex as needed to make the pb disappear (ex: uniquetag="banaNa11F453355B28E1158D4E516A2D3EDF96B3450406 ... )

                      – Olivier Dulac
                      May 13 at 13:54




                      1




                      1





                      Sure sure, it's not very likely, but anyways it might introduce a security issue later on. And then you might want to remove that string before printing to file ;-)

                      – pLumo
                      May 13 at 13:55






                      Sure sure, it's not very likely, but anyways it might introduce a security issue later on. And then you might want to remove that string before printing to file ;-)

                      – pLumo
                      May 13 at 13:55












                      2


















                      If order of output must be: stdout then stderr; there is no solution with redirection only.

                      The stderr must be stored to a temporal file



                      cmd 2>>file-err | tee -a file1 >>file2
                      cat file-err >> file1
                      rm file-err


                      Description:



                      The only way to redirect one output (an fd like stdout or stderr) to two files is to reproduce it. The command tee is the correct tool to reproduce a file descriptor content. So, an initial idea to have one output on two files would be to use:



                      ... | tee file1 file2


                      That reproduces the stdin of tee to both files (1 & 2) leaving the output of tee still unused. But we need to append (use -a) and only need one copy. This solve both issues:



                      ... | tee -a file1 >>file2


                      To supply tee with stdout (the one to repeat) we need to consume stderr directly out of the command. One way, if order is not important (order of output will (most probably) be preserved as generated, whichever is output first will be stored first). Either:



                      1. cmd 2>>file1 | tee -a file2 >>file1

                      2. cmd 2>>file1 > >( tee -a file2 >>file1 )

                      3. ( cmd | tee -a file2 ) >> file1 2>&1

                      Option 2 works only in some shells. Option 3 uses an additional subshell (slower) but use the file names only once.



                      But if stdout must be first (whichever order output is generated) we need to store stderr to append it to file at the end (first solution posted).






                      share|improve this answer























                      • 1





                        Or store in memory like sponge does: (cmd | tee -a out >> out+err) 2>&1 | sponge >> out+err

                        – Stéphane Chazelas
                        May 14 at 11:15















                      2


















                      If order of output must be: stdout then stderr; there is no solution with redirection only.

                      The stderr must be stored to a temporal file



                      cmd 2>>file-err | tee -a file1 >>file2
                      cat file-err >> file1
                      rm file-err


                      Description:



                      The only way to redirect one output (an fd like stdout or stderr) to two files is to reproduce it. The command tee is the correct tool to reproduce a file descriptor content. So, an initial idea to have one output on two files would be to use:



                      ... | tee file1 file2


                      That reproduces the stdin of tee to both files (1 & 2) leaving the output of tee still unused. But we need to append (use -a) and only need one copy. This solve both issues:



                      ... | tee -a file1 >>file2


                      To supply tee with stdout (the one to repeat) we need to consume stderr directly out of the command. One way, if order is not important (order of output will (most probably) be preserved as generated, whichever is output first will be stored first). Either:



                      1. cmd 2>>file1 | tee -a file2 >>file1

                      2. cmd 2>>file1 > >( tee -a file2 >>file1 )

                      3. ( cmd | tee -a file2 ) >> file1 2>&1

                      Option 2 works only in some shells. Option 3 uses an additional subshell (slower) but use the file names only once.



                      But if stdout must be first (whichever order output is generated) we need to store stderr to append it to file at the end (first solution posted).






                      share|improve this answer























                      • 1





                        Or store in memory like sponge does: (cmd | tee -a out >> out+err) 2>&1 | sponge >> out+err

                        – Stéphane Chazelas
                        May 14 at 11:15













                      2














                      2










                      2









                      If order of output must be: stdout then stderr; there is no solution with redirection only.

                      The stderr must be stored to a temporal file



                      cmd 2>>file-err | tee -a file1 >>file2
                      cat file-err >> file1
                      rm file-err


                      Description:



                      The only way to redirect one output (an fd like stdout or stderr) to two files is to reproduce it. The command tee is the correct tool to reproduce a file descriptor content. So, an initial idea to have one output on two files would be to use:



                      ... | tee file1 file2


                      That reproduces the stdin of tee to both files (1 & 2) leaving the output of tee still unused. But we need to append (use -a) and only need one copy. This solve both issues:



                      ... | tee -a file1 >>file2


                      To supply tee with stdout (the one to repeat) we need to consume stderr directly out of the command. One way, if order is not important (order of output will (most probably) be preserved as generated, whichever is output first will be stored first). Either:



                      1. cmd 2>>file1 | tee -a file2 >>file1

                      2. cmd 2>>file1 > >( tee -a file2 >>file1 )

                      3. ( cmd | tee -a file2 ) >> file1 2>&1

                      Option 2 works only in some shells. Option 3 uses an additional subshell (slower) but use the file names only once.



                      But if stdout must be first (whichever order output is generated) we need to store stderr to append it to file at the end (first solution posted).






                      share|improve this answer
















                      If order of output must be: stdout then stderr; there is no solution with redirection only.

                      The stderr must be stored to a temporal file



                      cmd 2>>file-err | tee -a file1 >>file2
                      cat file-err >> file1
                      rm file-err


                      Description:



                      The only way to redirect one output (an fd like stdout or stderr) to two files is to reproduce it. The command tee is the correct tool to reproduce a file descriptor content. So, an initial idea to have one output on two files would be to use:



                      ... | tee file1 file2


                      That reproduces the stdin of tee to both files (1 & 2) leaving the output of tee still unused. But we need to append (use -a) and only need one copy. This solve both issues:



                      ... | tee -a file1 >>file2


                      To supply tee with stdout (the one to repeat) we need to consume stderr directly out of the command. One way, if order is not important (order of output will (most probably) be preserved as generated, whichever is output first will be stored first). Either:



                      1. cmd 2>>file1 | tee -a file2 >>file1

                      2. cmd 2>>file1 > >( tee -a file2 >>file1 )

                      3. ( cmd | tee -a file2 ) >> file1 2>&1

                      Option 2 works only in some shells. Option 3 uses an additional subshell (slower) but use the file names only once.



                      But if stdout must be first (whichever order output is generated) we need to store stderr to append it to file at the end (first solution posted).







                      share|improve this answer















                      share|improve this answer




                      share|improve this answer








                      edited May 13 at 22:04

























                      answered May 13 at 21:53









                      IsaacIsaac

                      15.2k1 gold badge25 silver badges64 bronze badges




                      15.2k1 gold badge25 silver badges64 bronze badges










                      • 1





                        Or store in memory like sponge does: (cmd | tee -a out >> out+err) 2>&1 | sponge >> out+err

                        – Stéphane Chazelas
                        May 14 at 11:15












                      • 1





                        Or store in memory like sponge does: (cmd | tee -a out >> out+err) 2>&1 | sponge >> out+err

                        – Stéphane Chazelas
                        May 14 at 11:15







                      1




                      1





                      Or store in memory like sponge does: (cmd | tee -a out >> out+err) 2>&1 | sponge >> out+err

                      – Stéphane Chazelas
                      May 14 at 11:15





                      Or store in memory like sponge does: (cmd | tee -a out >> out+err) 2>&1 | sponge >> out+err

                      – Stéphane Chazelas
                      May 14 at 11:15











                      1


















                      In the interests of diversity:



                      If your system supports /dev/stderr, then



                      (cmd | tee -a /dev/stderr) 2>> file1 >> file2


                      will work. 
                      The standard output of the cmd
                      is sent to both the stdout and the stderr of the pipeline.
                      The standard error of the cmd bypasses the tee
                      and comes out the stderr of the pipeline.



                      So



                      • the stdout of the pipeline is just the stdout of the cmd, and

                      • the stderr of the pipeline is the stdout and stderr of the cmd,
                        intermixed.

                      It's then a simple matter of sending those streams to the correct files.



                      As with almost any approach like this (including Stéphane’s answer),
                      file1 may get lines out of order.






                      share|improve this answer






























                        1


















                        In the interests of diversity:



                        If your system supports /dev/stderr, then



                        (cmd | tee -a /dev/stderr) 2>> file1 >> file2


                        will work. 
                        The standard output of the cmd
                        is sent to both the stdout and the stderr of the pipeline.
                        The standard error of the cmd bypasses the tee
                        and comes out the stderr of the pipeline.



                        So



                        • the stdout of the pipeline is just the stdout of the cmd, and

                        • the stderr of the pipeline is the stdout and stderr of the cmd,
                          intermixed.

                        It's then a simple matter of sending those streams to the correct files.



                        As with almost any approach like this (including Stéphane’s answer),
                        file1 may get lines out of order.






                        share|improve this answer




























                          1














                          1










                          1









                          In the interests of diversity:



                          If your system supports /dev/stderr, then



                          (cmd | tee -a /dev/stderr) 2>> file1 >> file2


                          will work. 
                          The standard output of the cmd
                          is sent to both the stdout and the stderr of the pipeline.
                          The standard error of the cmd bypasses the tee
                          and comes out the stderr of the pipeline.



                          So



                          • the stdout of the pipeline is just the stdout of the cmd, and

                          • the stderr of the pipeline is the stdout and stderr of the cmd,
                            intermixed.

                          It's then a simple matter of sending those streams to the correct files.



                          As with almost any approach like this (including Stéphane’s answer),
                          file1 may get lines out of order.






                          share|improve this answer














                          In the interests of diversity:



                          If your system supports /dev/stderr, then



                          (cmd | tee -a /dev/stderr) 2>> file1 >> file2


                          will work. 
                          The standard output of the cmd
                          is sent to both the stdout and the stderr of the pipeline.
                          The standard error of the cmd bypasses the tee
                          and comes out the stderr of the pipeline.



                          So



                          • the stdout of the pipeline is just the stdout of the cmd, and

                          • the stderr of the pipeline is the stdout and stderr of the cmd,
                            intermixed.

                          It's then a simple matter of sending those streams to the correct files.



                          As with almost any approach like this (including Stéphane’s answer),
                          file1 may get lines out of order.







                          share|improve this answer













                          share|improve this answer




                          share|improve this answer










                          answered May 14 at 19:27









                          ScottScott

                          7,6525 gold badges30 silver badges54 bronze badges




                          7,6525 gold badges30 silver badges54 bronze badges































                              draft saved

                              draft discarded















































                              Thanks for contributing an answer to Unix & Linux Stack Exchange!


                              • Please be sure to answer the question. Provide details and share your research!

                              But avoid


                              • Asking for help, clarification, or responding to other answers.

                              • Making statements based on opinion; back them up with references or personal experience.

                              To learn more, see our tips on writing great answers.




                              draft saved


                              draft discarded














                              StackExchange.ready(
                              function ()
                              StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2funix.stackexchange.com%2fquestions%2f518655%2fhow-to-redirect-stdout-to-a-file-and-stdoutstderr-to-another-one%23new-answer', 'question_page');

                              );

                              Post as a guest















                              Required, but never shown





















































                              Required, but never shown














                              Required, but never shown












                              Required, but never shown







                              Required, but never shown

































                              Required, but never shown














                              Required, but never shown












                              Required, but never shown







                              Required, but never shown









                              Popular posts from this blog

                              Tamil (spriik) Luke uk diar | Nawigatjuun

                              Align equal signs while including text over equalitiesAMS align: left aligned text/math plus multicolumn alignmentMultiple alignmentsAligning equations in multiple placesNumbering and aligning an equation with multiple columnsHow to align one equation with another multline equationUsing \ in environments inside the begintabularxNumber equations and preserving alignment of equal signsHow can I align equations to the left and to the right?Double equation alignment problem within align enviromentAligned within align: Why are they right-aligned?

                              Where does the image of a data connector as a sharp metal spike originate from?Where does the concept of infected people turning into zombies only after death originate from?Where does the motif of a reanimated human head originate?Where did the notion that Dragons could speak originate?Where does the archetypal image of the 'Grey' alien come from?Where did the suffix '-Man' originate?Where does the notion of being injured or killed by an illusion originate?Where did the term “sophont” originate?Where does the trope of magic spells being driven by advanced technology originate from?Where did the term “the living impaired” originate?