Capture stdout to a variable but still display it in the console





.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty{ height:90px;width:728px;box-sizing:border-box;
}







63















I have a bash script which calls several long-running processes. I want to capture the output of those calls into variables for processing reasons. However, because these are long running processes, I would like the output of the rsync calls to be displayed in the console in real-time and not after the fact.



To this end, I have found a way of doing it but it relies on outputting the text to /dev/stderr. I feel that outputting to /dev/stderr is not a good way of doing things.



VAR1=$(for i in {1..5}; do sleep 1; echo $i; done | tee /dev/stderr)

VAR2=$(rsync -r -t --out-format='%n%L' --delete -s /path/source1/ /path/target1 | tee /dev/stderr)

VAR3=$(rsync -r -t --out-format='%n%L' --delete -s /path/source2/ /path/target2 | tee /dev/stderr)


In the example above, I am calling rsync a few times and I want to see the file names as they are processed, but in the end I still want the output in a variable because I will be parsing it later.



Is there a 'cleaner' way of accomplishing this?



If it makes a difference, I am using Ubuntu 12.04, bash 4.2.24.










share|improve this question































    63















    I have a bash script which calls several long-running processes. I want to capture the output of those calls into variables for processing reasons. However, because these are long running processes, I would like the output of the rsync calls to be displayed in the console in real-time and not after the fact.



    To this end, I have found a way of doing it but it relies on outputting the text to /dev/stderr. I feel that outputting to /dev/stderr is not a good way of doing things.



    VAR1=$(for i in {1..5}; do sleep 1; echo $i; done | tee /dev/stderr)

    VAR2=$(rsync -r -t --out-format='%n%L' --delete -s /path/source1/ /path/target1 | tee /dev/stderr)

    VAR3=$(rsync -r -t --out-format='%n%L' --delete -s /path/source2/ /path/target2 | tee /dev/stderr)


    In the example above, I am calling rsync a few times and I want to see the file names as they are processed, but in the end I still want the output in a variable because I will be parsing it later.



    Is there a 'cleaner' way of accomplishing this?



    If it makes a difference, I am using Ubuntu 12.04, bash 4.2.24.










    share|improve this question



























      63












      63








      63


      16






      I have a bash script which calls several long-running processes. I want to capture the output of those calls into variables for processing reasons. However, because these are long running processes, I would like the output of the rsync calls to be displayed in the console in real-time and not after the fact.



      To this end, I have found a way of doing it but it relies on outputting the text to /dev/stderr. I feel that outputting to /dev/stderr is not a good way of doing things.



      VAR1=$(for i in {1..5}; do sleep 1; echo $i; done | tee /dev/stderr)

      VAR2=$(rsync -r -t --out-format='%n%L' --delete -s /path/source1/ /path/target1 | tee /dev/stderr)

      VAR3=$(rsync -r -t --out-format='%n%L' --delete -s /path/source2/ /path/target2 | tee /dev/stderr)


      In the example above, I am calling rsync a few times and I want to see the file names as they are processed, but in the end I still want the output in a variable because I will be parsing it later.



      Is there a 'cleaner' way of accomplishing this?



      If it makes a difference, I am using Ubuntu 12.04, bash 4.2.24.










      share|improve this question
















      I have a bash script which calls several long-running processes. I want to capture the output of those calls into variables for processing reasons. However, because these are long running processes, I would like the output of the rsync calls to be displayed in the console in real-time and not after the fact.



      To this end, I have found a way of doing it but it relies on outputting the text to /dev/stderr. I feel that outputting to /dev/stderr is not a good way of doing things.



      VAR1=$(for i in {1..5}; do sleep 1; echo $i; done | tee /dev/stderr)

      VAR2=$(rsync -r -t --out-format='%n%L' --delete -s /path/source1/ /path/target1 | tee /dev/stderr)

      VAR3=$(rsync -r -t --out-format='%n%L' --delete -s /path/source2/ /path/target2 | tee /dev/stderr)


      In the example above, I am calling rsync a few times and I want to see the file names as they are processed, but in the end I still want the output in a variable because I will be parsing it later.



      Is there a 'cleaner' way of accomplishing this?



      If it makes a difference, I am using Ubuntu 12.04, bash 4.2.24.







      bash ubuntu tee process-substitution






      share|improve this question















      share|improve this question













      share|improve this question




      share|improve this question








      edited Sep 9 '18 at 0:11









      jww

      54.2k41234515




      54.2k41234515










      asked Sep 16 '12 at 22:30









      MendhakMendhak

      4,79633854




      4,79633854
























          5 Answers
          5






          active

          oldest

          votes


















          71














          Duplicate &1 in your shell (in my examle to 5) and use &5 in the subshell (so that you will write to stdout (&1) of the parent shell):



          exec 5>&1
          FF=$(echo aaa|tee >(cat - >&5))
          echo $FF


          Will print aaa two times, ones because of the echo in the subshell, and second time print the value of the variable.



          In your code:



          exec 5>&1
          VAR1=$(for i in {1..5}; do sleep 1; echo $i; done | tee >(cat - >&5))
          # use the value of VAR1





          share|improve this answer
























          • This worked, thanks! So in this case, is the '5' must be a file descriptor, I will read up and learn about these.

            – Mendhak
            Sep 17 '12 at 5:15






          • 3





            Shouldn't the descriptor be closed in the parent shell?

            – akhan
            Mar 11 '14 at 5:27








          • 2





            @akhan: I assume that's exec 5>&- then?

            – hakre
            Sep 29 '14 at 13:03






          • 5





            How about FF=$(echo aaa | tee /dev/tty)? Source

            – knight42
            Dec 30 '15 at 5:40






          • 1





            This does not preserve output colors.

            – Shantanu Bhadoria
            May 1 '17 at 0:57



















          33














          Op De Cirkel's answer has the right idea. It can be simplified even more (avoiding use of cat):



          exec 5>&1
          FF=$(echo aaa|tee /dev/fd/5)
          echo $FF





          share|improve this answer



















          • 6





            Wouldn't /dev/fd/5 be OS specific?

            – akhan
            Mar 11 '14 at 5:25






          • 9





            I had been wondering if you could just use tee /dev/fd/1, but that doesn't work because the output still gets captured by $(). So in case anyone else is wondering the same thing, it is necessary to use an extra file descriptor (like 5).

            – dirtside
            Sep 20 '15 at 18:42








          • 1





            We could go simplifying even further and making this a oneliner without the exec: { FF=$(echo aaa|tee /dev/fd/5); } 5>&1 The braces allow for the redirection to happen before the subshell command is run, while $FF still remains in the scope of the current shell (that wouldn't work with normal brackets ( ). This way there's even no need to close FD 5 afterwards, which is a overlooked hygienic habit.

            – tlwhitec
            May 11 '18 at 8:30













          • @akhan No it wouldn't, bash is said to be emulating this path should it not exist in the OS by itself.

            – tlwhitec
            May 11 '18 at 8:32



















          11














          Here's an example capturing both stderr and the command's exit code. This is building on the answer by Russell Davis.



          exec 5>&1
          FF=$(ls /taco/ 2>&1 |tee /dev/fd/5; exit ${PIPESTATUS[0]})
          exit_code=$?
          echo "$FF"
          echo "Exit Code: $exit_code"


          If the folder /taco/ exists, this will capture its contents. If the folder doesn't exist, it will capture an error message and the exit code will be 2.



          If you omit 2>&1then only stdout will be captured.






          share|improve this answer































            5














            You can use more than three file descriptors. Try here:



            http://tldp.org/LDP/abs/html/io-redirection.html



            "Each open file gets assigned a file descriptor. [2] The file descriptors for stdin, stdout, and stderr are 0, 1, and 2, respectively. For opening additional files, there remain descriptors 3 to 9. It is sometimes useful to assign one of these additional file descriptors to stdin, stdout, or stderr as a temporary duplicate link."



            The point is whether it's worth to make script more complicated just to achieve this result. Actually it's not really wrong, the way you do it.






            share|improve this answer































              2














              If by "the console" you mean your current TTY, try



              variable=$(command with options | tee /dev/tty)


              This is slightly dubious practice because people who try to use this sometimes are surprised when the output lands somewhere unexpected when they don't have a TTY (cron jobs etc).






              share|improve this answer
























                Your Answer






                StackExchange.ifUsing("editor", function () {
                StackExchange.using("externalEditor", function () {
                StackExchange.using("snippets", function () {
                StackExchange.snippets.init();
                });
                });
                }, "code-snippets");

                StackExchange.ready(function() {
                var channelOptions = {
                tags: "".split(" "),
                id: "1"
                };
                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: true,
                noModals: true,
                showLowRepImageUploadWarning: true,
                reputationToPostImages: 10,
                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/3.0/"u003ecc by-sa 3.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%2fstackoverflow.com%2fquestions%2f12451278%2fcapture-stdout-to-a-variable-but-still-display-it-in-the-console%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









                71














                Duplicate &1 in your shell (in my examle to 5) and use &5 in the subshell (so that you will write to stdout (&1) of the parent shell):



                exec 5>&1
                FF=$(echo aaa|tee >(cat - >&5))
                echo $FF


                Will print aaa two times, ones because of the echo in the subshell, and second time print the value of the variable.



                In your code:



                exec 5>&1
                VAR1=$(for i in {1..5}; do sleep 1; echo $i; done | tee >(cat - >&5))
                # use the value of VAR1





                share|improve this answer
























                • This worked, thanks! So in this case, is the '5' must be a file descriptor, I will read up and learn about these.

                  – Mendhak
                  Sep 17 '12 at 5:15






                • 3





                  Shouldn't the descriptor be closed in the parent shell?

                  – akhan
                  Mar 11 '14 at 5:27








                • 2





                  @akhan: I assume that's exec 5>&- then?

                  – hakre
                  Sep 29 '14 at 13:03






                • 5





                  How about FF=$(echo aaa | tee /dev/tty)? Source

                  – knight42
                  Dec 30 '15 at 5:40






                • 1





                  This does not preserve output colors.

                  – Shantanu Bhadoria
                  May 1 '17 at 0:57
















                71














                Duplicate &1 in your shell (in my examle to 5) and use &5 in the subshell (so that you will write to stdout (&1) of the parent shell):



                exec 5>&1
                FF=$(echo aaa|tee >(cat - >&5))
                echo $FF


                Will print aaa two times, ones because of the echo in the subshell, and second time print the value of the variable.



                In your code:



                exec 5>&1
                VAR1=$(for i in {1..5}; do sleep 1; echo $i; done | tee >(cat - >&5))
                # use the value of VAR1





                share|improve this answer
























                • This worked, thanks! So in this case, is the '5' must be a file descriptor, I will read up and learn about these.

                  – Mendhak
                  Sep 17 '12 at 5:15






                • 3





                  Shouldn't the descriptor be closed in the parent shell?

                  – akhan
                  Mar 11 '14 at 5:27








                • 2





                  @akhan: I assume that's exec 5>&- then?

                  – hakre
                  Sep 29 '14 at 13:03






                • 5





                  How about FF=$(echo aaa | tee /dev/tty)? Source

                  – knight42
                  Dec 30 '15 at 5:40






                • 1





                  This does not preserve output colors.

                  – Shantanu Bhadoria
                  May 1 '17 at 0:57














                71












                71








                71







                Duplicate &1 in your shell (in my examle to 5) and use &5 in the subshell (so that you will write to stdout (&1) of the parent shell):



                exec 5>&1
                FF=$(echo aaa|tee >(cat - >&5))
                echo $FF


                Will print aaa two times, ones because of the echo in the subshell, and second time print the value of the variable.



                In your code:



                exec 5>&1
                VAR1=$(for i in {1..5}; do sleep 1; echo $i; done | tee >(cat - >&5))
                # use the value of VAR1





                share|improve this answer













                Duplicate &1 in your shell (in my examle to 5) and use &5 in the subshell (so that you will write to stdout (&1) of the parent shell):



                exec 5>&1
                FF=$(echo aaa|tee >(cat - >&5))
                echo $FF


                Will print aaa two times, ones because of the echo in the subshell, and second time print the value of the variable.



                In your code:



                exec 5>&1
                VAR1=$(for i in {1..5}; do sleep 1; echo $i; done | tee >(cat - >&5))
                # use the value of VAR1






                share|improve this answer












                share|improve this answer



                share|improve this answer










                answered Sep 16 '12 at 22:58









                Op De CirkelOp De Cirkel

                22.3k63044




                22.3k63044













                • This worked, thanks! So in this case, is the '5' must be a file descriptor, I will read up and learn about these.

                  – Mendhak
                  Sep 17 '12 at 5:15






                • 3





                  Shouldn't the descriptor be closed in the parent shell?

                  – akhan
                  Mar 11 '14 at 5:27








                • 2





                  @akhan: I assume that's exec 5>&- then?

                  – hakre
                  Sep 29 '14 at 13:03






                • 5





                  How about FF=$(echo aaa | tee /dev/tty)? Source

                  – knight42
                  Dec 30 '15 at 5:40






                • 1





                  This does not preserve output colors.

                  – Shantanu Bhadoria
                  May 1 '17 at 0:57



















                • This worked, thanks! So in this case, is the '5' must be a file descriptor, I will read up and learn about these.

                  – Mendhak
                  Sep 17 '12 at 5:15






                • 3





                  Shouldn't the descriptor be closed in the parent shell?

                  – akhan
                  Mar 11 '14 at 5:27








                • 2





                  @akhan: I assume that's exec 5>&- then?

                  – hakre
                  Sep 29 '14 at 13:03






                • 5





                  How about FF=$(echo aaa | tee /dev/tty)? Source

                  – knight42
                  Dec 30 '15 at 5:40






                • 1





                  This does not preserve output colors.

                  – Shantanu Bhadoria
                  May 1 '17 at 0:57

















                This worked, thanks! So in this case, is the '5' must be a file descriptor, I will read up and learn about these.

                – Mendhak
                Sep 17 '12 at 5:15





                This worked, thanks! So in this case, is the '5' must be a file descriptor, I will read up and learn about these.

                – Mendhak
                Sep 17 '12 at 5:15




                3




                3





                Shouldn't the descriptor be closed in the parent shell?

                – akhan
                Mar 11 '14 at 5:27







                Shouldn't the descriptor be closed in the parent shell?

                – akhan
                Mar 11 '14 at 5:27






                2




                2





                @akhan: I assume that's exec 5>&- then?

                – hakre
                Sep 29 '14 at 13:03





                @akhan: I assume that's exec 5>&- then?

                – hakre
                Sep 29 '14 at 13:03




                5




                5





                How about FF=$(echo aaa | tee /dev/tty)? Source

                – knight42
                Dec 30 '15 at 5:40





                How about FF=$(echo aaa | tee /dev/tty)? Source

                – knight42
                Dec 30 '15 at 5:40




                1




                1





                This does not preserve output colors.

                – Shantanu Bhadoria
                May 1 '17 at 0:57





                This does not preserve output colors.

                – Shantanu Bhadoria
                May 1 '17 at 0:57













                33














                Op De Cirkel's answer has the right idea. It can be simplified even more (avoiding use of cat):



                exec 5>&1
                FF=$(echo aaa|tee /dev/fd/5)
                echo $FF





                share|improve this answer



















                • 6





                  Wouldn't /dev/fd/5 be OS specific?

                  – akhan
                  Mar 11 '14 at 5:25






                • 9





                  I had been wondering if you could just use tee /dev/fd/1, but that doesn't work because the output still gets captured by $(). So in case anyone else is wondering the same thing, it is necessary to use an extra file descriptor (like 5).

                  – dirtside
                  Sep 20 '15 at 18:42








                • 1





                  We could go simplifying even further and making this a oneliner without the exec: { FF=$(echo aaa|tee /dev/fd/5); } 5>&1 The braces allow for the redirection to happen before the subshell command is run, while $FF still remains in the scope of the current shell (that wouldn't work with normal brackets ( ). This way there's even no need to close FD 5 afterwards, which is a overlooked hygienic habit.

                  – tlwhitec
                  May 11 '18 at 8:30













                • @akhan No it wouldn't, bash is said to be emulating this path should it not exist in the OS by itself.

                  – tlwhitec
                  May 11 '18 at 8:32
















                33














                Op De Cirkel's answer has the right idea. It can be simplified even more (avoiding use of cat):



                exec 5>&1
                FF=$(echo aaa|tee /dev/fd/5)
                echo $FF





                share|improve this answer



















                • 6





                  Wouldn't /dev/fd/5 be OS specific?

                  – akhan
                  Mar 11 '14 at 5:25






                • 9





                  I had been wondering if you could just use tee /dev/fd/1, but that doesn't work because the output still gets captured by $(). So in case anyone else is wondering the same thing, it is necessary to use an extra file descriptor (like 5).

                  – dirtside
                  Sep 20 '15 at 18:42








                • 1





                  We could go simplifying even further and making this a oneliner without the exec: { FF=$(echo aaa|tee /dev/fd/5); } 5>&1 The braces allow for the redirection to happen before the subshell command is run, while $FF still remains in the scope of the current shell (that wouldn't work with normal brackets ( ). This way there's even no need to close FD 5 afterwards, which is a overlooked hygienic habit.

                  – tlwhitec
                  May 11 '18 at 8:30













                • @akhan No it wouldn't, bash is said to be emulating this path should it not exist in the OS by itself.

                  – tlwhitec
                  May 11 '18 at 8:32














                33












                33








                33







                Op De Cirkel's answer has the right idea. It can be simplified even more (avoiding use of cat):



                exec 5>&1
                FF=$(echo aaa|tee /dev/fd/5)
                echo $FF





                share|improve this answer













                Op De Cirkel's answer has the right idea. It can be simplified even more (avoiding use of cat):



                exec 5>&1
                FF=$(echo aaa|tee /dev/fd/5)
                echo $FF






                share|improve this answer












                share|improve this answer



                share|improve this answer










                answered Apr 30 '13 at 4:25









                Russell DavisRussell Davis

                5,41433239




                5,41433239








                • 6





                  Wouldn't /dev/fd/5 be OS specific?

                  – akhan
                  Mar 11 '14 at 5:25






                • 9





                  I had been wondering if you could just use tee /dev/fd/1, but that doesn't work because the output still gets captured by $(). So in case anyone else is wondering the same thing, it is necessary to use an extra file descriptor (like 5).

                  – dirtside
                  Sep 20 '15 at 18:42








                • 1





                  We could go simplifying even further and making this a oneliner without the exec: { FF=$(echo aaa|tee /dev/fd/5); } 5>&1 The braces allow for the redirection to happen before the subshell command is run, while $FF still remains in the scope of the current shell (that wouldn't work with normal brackets ( ). This way there's even no need to close FD 5 afterwards, which is a overlooked hygienic habit.

                  – tlwhitec
                  May 11 '18 at 8:30













                • @akhan No it wouldn't, bash is said to be emulating this path should it not exist in the OS by itself.

                  – tlwhitec
                  May 11 '18 at 8:32














                • 6





                  Wouldn't /dev/fd/5 be OS specific?

                  – akhan
                  Mar 11 '14 at 5:25






                • 9





                  I had been wondering if you could just use tee /dev/fd/1, but that doesn't work because the output still gets captured by $(). So in case anyone else is wondering the same thing, it is necessary to use an extra file descriptor (like 5).

                  – dirtside
                  Sep 20 '15 at 18:42








                • 1





                  We could go simplifying even further and making this a oneliner without the exec: { FF=$(echo aaa|tee /dev/fd/5); } 5>&1 The braces allow for the redirection to happen before the subshell command is run, while $FF still remains in the scope of the current shell (that wouldn't work with normal brackets ( ). This way there's even no need to close FD 5 afterwards, which is a overlooked hygienic habit.

                  – tlwhitec
                  May 11 '18 at 8:30













                • @akhan No it wouldn't, bash is said to be emulating this path should it not exist in the OS by itself.

                  – tlwhitec
                  May 11 '18 at 8:32








                6




                6





                Wouldn't /dev/fd/5 be OS specific?

                – akhan
                Mar 11 '14 at 5:25





                Wouldn't /dev/fd/5 be OS specific?

                – akhan
                Mar 11 '14 at 5:25




                9




                9





                I had been wondering if you could just use tee /dev/fd/1, but that doesn't work because the output still gets captured by $(). So in case anyone else is wondering the same thing, it is necessary to use an extra file descriptor (like 5).

                – dirtside
                Sep 20 '15 at 18:42







                I had been wondering if you could just use tee /dev/fd/1, but that doesn't work because the output still gets captured by $(). So in case anyone else is wondering the same thing, it is necessary to use an extra file descriptor (like 5).

                – dirtside
                Sep 20 '15 at 18:42






                1




                1





                We could go simplifying even further and making this a oneliner without the exec: { FF=$(echo aaa|tee /dev/fd/5); } 5>&1 The braces allow for the redirection to happen before the subshell command is run, while $FF still remains in the scope of the current shell (that wouldn't work with normal brackets ( ). This way there's even no need to close FD 5 afterwards, which is a overlooked hygienic habit.

                – tlwhitec
                May 11 '18 at 8:30







                We could go simplifying even further and making this a oneliner without the exec: { FF=$(echo aaa|tee /dev/fd/5); } 5>&1 The braces allow for the redirection to happen before the subshell command is run, while $FF still remains in the scope of the current shell (that wouldn't work with normal brackets ( ). This way there's even no need to close FD 5 afterwards, which is a overlooked hygienic habit.

                – tlwhitec
                May 11 '18 at 8:30















                @akhan No it wouldn't, bash is said to be emulating this path should it not exist in the OS by itself.

                – tlwhitec
                May 11 '18 at 8:32





                @akhan No it wouldn't, bash is said to be emulating this path should it not exist in the OS by itself.

                – tlwhitec
                May 11 '18 at 8:32











                11














                Here's an example capturing both stderr and the command's exit code. This is building on the answer by Russell Davis.



                exec 5>&1
                FF=$(ls /taco/ 2>&1 |tee /dev/fd/5; exit ${PIPESTATUS[0]})
                exit_code=$?
                echo "$FF"
                echo "Exit Code: $exit_code"


                If the folder /taco/ exists, this will capture its contents. If the folder doesn't exist, it will capture an error message and the exit code will be 2.



                If you omit 2>&1then only stdout will be captured.






                share|improve this answer




























                  11














                  Here's an example capturing both stderr and the command's exit code. This is building on the answer by Russell Davis.



                  exec 5>&1
                  FF=$(ls /taco/ 2>&1 |tee /dev/fd/5; exit ${PIPESTATUS[0]})
                  exit_code=$?
                  echo "$FF"
                  echo "Exit Code: $exit_code"


                  If the folder /taco/ exists, this will capture its contents. If the folder doesn't exist, it will capture an error message and the exit code will be 2.



                  If you omit 2>&1then only stdout will be captured.






                  share|improve this answer


























                    11












                    11








                    11







                    Here's an example capturing both stderr and the command's exit code. This is building on the answer by Russell Davis.



                    exec 5>&1
                    FF=$(ls /taco/ 2>&1 |tee /dev/fd/5; exit ${PIPESTATUS[0]})
                    exit_code=$?
                    echo "$FF"
                    echo "Exit Code: $exit_code"


                    If the folder /taco/ exists, this will capture its contents. If the folder doesn't exist, it will capture an error message and the exit code will be 2.



                    If you omit 2>&1then only stdout will be captured.






                    share|improve this answer













                    Here's an example capturing both stderr and the command's exit code. This is building on the answer by Russell Davis.



                    exec 5>&1
                    FF=$(ls /taco/ 2>&1 |tee /dev/fd/5; exit ${PIPESTATUS[0]})
                    exit_code=$?
                    echo "$FF"
                    echo "Exit Code: $exit_code"


                    If the folder /taco/ exists, this will capture its contents. If the folder doesn't exist, it will capture an error message and the exit code will be 2.



                    If you omit 2>&1then only stdout will be captured.







                    share|improve this answer












                    share|improve this answer



                    share|improve this answer










                    answered Jan 30 '17 at 19:18









                    Bryan RoachBryan Roach

                    39359




                    39359























                        5














                        You can use more than three file descriptors. Try here:



                        http://tldp.org/LDP/abs/html/io-redirection.html



                        "Each open file gets assigned a file descriptor. [2] The file descriptors for stdin, stdout, and stderr are 0, 1, and 2, respectively. For opening additional files, there remain descriptors 3 to 9. It is sometimes useful to assign one of these additional file descriptors to stdin, stdout, or stderr as a temporary duplicate link."



                        The point is whether it's worth to make script more complicated just to achieve this result. Actually it's not really wrong, the way you do it.






                        share|improve this answer




























                          5














                          You can use more than three file descriptors. Try here:



                          http://tldp.org/LDP/abs/html/io-redirection.html



                          "Each open file gets assigned a file descriptor. [2] The file descriptors for stdin, stdout, and stderr are 0, 1, and 2, respectively. For opening additional files, there remain descriptors 3 to 9. It is sometimes useful to assign one of these additional file descriptors to stdin, stdout, or stderr as a temporary duplicate link."



                          The point is whether it's worth to make script more complicated just to achieve this result. Actually it's not really wrong, the way you do it.






                          share|improve this answer


























                            5












                            5








                            5







                            You can use more than three file descriptors. Try here:



                            http://tldp.org/LDP/abs/html/io-redirection.html



                            "Each open file gets assigned a file descriptor. [2] The file descriptors for stdin, stdout, and stderr are 0, 1, and 2, respectively. For opening additional files, there remain descriptors 3 to 9. It is sometimes useful to assign one of these additional file descriptors to stdin, stdout, or stderr as a temporary duplicate link."



                            The point is whether it's worth to make script more complicated just to achieve this result. Actually it's not really wrong, the way you do it.






                            share|improve this answer













                            You can use more than three file descriptors. Try here:



                            http://tldp.org/LDP/abs/html/io-redirection.html



                            "Each open file gets assigned a file descriptor. [2] The file descriptors for stdin, stdout, and stderr are 0, 1, and 2, respectively. For opening additional files, there remain descriptors 3 to 9. It is sometimes useful to assign one of these additional file descriptors to stdin, stdout, or stderr as a temporary duplicate link."



                            The point is whether it's worth to make script more complicated just to achieve this result. Actually it's not really wrong, the way you do it.







                            share|improve this answer












                            share|improve this answer



                            share|improve this answer










                            answered Sep 16 '12 at 22:41









                            Piotr WadasPiotr Wadas

                            1,7041712




                            1,7041712























                                2














                                If by "the console" you mean your current TTY, try



                                variable=$(command with options | tee /dev/tty)


                                This is slightly dubious practice because people who try to use this sometimes are surprised when the output lands somewhere unexpected when they don't have a TTY (cron jobs etc).






                                share|improve this answer




























                                  2














                                  If by "the console" you mean your current TTY, try



                                  variable=$(command with options | tee /dev/tty)


                                  This is slightly dubious practice because people who try to use this sometimes are surprised when the output lands somewhere unexpected when they don't have a TTY (cron jobs etc).






                                  share|improve this answer


























                                    2












                                    2








                                    2







                                    If by "the console" you mean your current TTY, try



                                    variable=$(command with options | tee /dev/tty)


                                    This is slightly dubious practice because people who try to use this sometimes are surprised when the output lands somewhere unexpected when they don't have a TTY (cron jobs etc).






                                    share|improve this answer













                                    If by "the console" you mean your current TTY, try



                                    variable=$(command with options | tee /dev/tty)


                                    This is slightly dubious practice because people who try to use this sometimes are surprised when the output lands somewhere unexpected when they don't have a TTY (cron jobs etc).







                                    share|improve this answer












                                    share|improve this answer



                                    share|improve this answer










                                    answered Nov 16 '18 at 12:50









                                    tripleeetripleee

                                    96k13133190




                                    96k13133190






























                                        draft saved

                                        draft discarded




















































                                        Thanks for contributing an answer to Stack Overflow!


                                        • 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%2fstackoverflow.com%2fquestions%2f12451278%2fcapture-stdout-to-a-variable-but-still-display-it-in-the-console%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

                                        The Sandy Post

                                        Danny Elfman

                                        Pages that link to "Head v. Amoskeag Manufacturing Co."