How to get the result of command substitution without using stdio and stderr?












0














I have a user-provided bash script that creates a directory in some way and outputs its path. It can work in many ways, for example, it can clone a git repository, do some setting up, and then output the path. Something like this:



git clone ...repo --quiet && echo "...path"


I run it using command substitution, wrapping with $(...) and using the resulting path. Something like this:



path=$(...)


The command itself is user-provided, so it can be anything, I can't anticipate it will always be git clone.



It works well, but if the commands before the final echo outputs anything, it will mess up the result. I could redirect stdout to stderr for all preceding commands and only use stdout at the last step, but I feel it's a hack.



Is there any way to leave stdout and stderr to the caller's stdout and stderr, but have a separate stream for the result?










share|improve this question
























  • Having a "separate stream for the result" is exactly what stdout is (as distinct from stderr).
    – Gordon Davisson
    Dec 13 at 17:14
















0














I have a user-provided bash script that creates a directory in some way and outputs its path. It can work in many ways, for example, it can clone a git repository, do some setting up, and then output the path. Something like this:



git clone ...repo --quiet && echo "...path"


I run it using command substitution, wrapping with $(...) and using the resulting path. Something like this:



path=$(...)


The command itself is user-provided, so it can be anything, I can't anticipate it will always be git clone.



It works well, but if the commands before the final echo outputs anything, it will mess up the result. I could redirect stdout to stderr for all preceding commands and only use stdout at the last step, but I feel it's a hack.



Is there any way to leave stdout and stderr to the caller's stdout and stderr, but have a separate stream for the result?










share|improve this question
























  • Having a "separate stream for the result" is exactly what stdout is (as distinct from stderr).
    – Gordon Davisson
    Dec 13 at 17:14














0












0








0







I have a user-provided bash script that creates a directory in some way and outputs its path. It can work in many ways, for example, it can clone a git repository, do some setting up, and then output the path. Something like this:



git clone ...repo --quiet && echo "...path"


I run it using command substitution, wrapping with $(...) and using the resulting path. Something like this:



path=$(...)


The command itself is user-provided, so it can be anything, I can't anticipate it will always be git clone.



It works well, but if the commands before the final echo outputs anything, it will mess up the result. I could redirect stdout to stderr for all preceding commands and only use stdout at the last step, but I feel it's a hack.



Is there any way to leave stdout and stderr to the caller's stdout and stderr, but have a separate stream for the result?










share|improve this question















I have a user-provided bash script that creates a directory in some way and outputs its path. It can work in many ways, for example, it can clone a git repository, do some setting up, and then output the path. Something like this:



git clone ...repo --quiet && echo "...path"


I run it using command substitution, wrapping with $(...) and using the resulting path. Something like this:



path=$(...)


The command itself is user-provided, so it can be anything, I can't anticipate it will always be git clone.



It works well, but if the commands before the final echo outputs anything, it will mess up the result. I could redirect stdout to stderr for all preceding commands and only use stdout at the last step, but I feel it's a hack.



Is there any way to leave stdout and stderr to the caller's stdout and stderr, but have a separate stream for the result?







bash






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Dec 13 at 11:51









Kamil Maciorowski

23.7k155074




23.7k155074










asked Dec 13 at 11:35









sashee

1031




1031












  • Having a "separate stream for the result" is exactly what stdout is (as distinct from stderr).
    – Gordon Davisson
    Dec 13 at 17:14


















  • Having a "separate stream for the result" is exactly what stdout is (as distinct from stderr).
    – Gordon Davisson
    Dec 13 at 17:14
















Having a "separate stream for the result" is exactly what stdout is (as distinct from stderr).
– Gordon Davisson
Dec 13 at 17:14




Having a "separate stream for the result" is exactly what stdout is (as distinct from stderr).
– Gordon Davisson
Dec 13 at 17:14










1 Answer
1






active

oldest

votes


















1














This will save the last line of output:



path=$(whatever | tail -n 1)


If you need all the output to be utilized in some way:





  • use tee to print the output to the tty



    path=$(whatever | tee /dev/tty | tail -n 1)



  • or to save it



    path=$(whatever | tee ./file | tail -n 1)



  • or to process it (and print to the tty or a file, not to stdout which feeds the variable)



    path=$(whatever | tee >(grep foo | wc -c >/dev/tty) | tail -n 1)



  • You can even send (fork) the output to many destinations:



    path=$(whatever | tee /dev/tty ./file /some/named/fifo >(tool1) | tail -n 1)



Obviously a newline within the echoed path will break the solution.





If you can modify the final echo command in the user-provided script then please see this answer of mine for an approach that uses temporary files.






share|improve this answer























  • It works if I want it to go to the terminal, but what if the stdout is redirected somewhere? I have a test.sh: path=$((echo "doing something..." && echo "path") | tee /dev/tty | tail -1) && echo $path > result If I call it with ./test.sh > log.txt, it still outputs to the terminal. Is there any way to support this? I'd like to have both lines in the log.txt, and only the "path" in the result.
    – sashee
    Dec 13 at 11:58












  • Thank you, that link was a good guidance, I decided to go on the tempfile approach. This is the script I came up with: function dosth () { echo "doing something..."; echo "path" >$1; }; result_tmp=$(mktemp); trap 'rm $result_tmp' EXIT; dosth $result_tmp; path=$(cat $result_tmp); echo path > result
    – sashee
    Dec 13 at 14:08











Your Answer








StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "3"
};
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%2fsuperuser.com%2fquestions%2f1383268%2fhow-to-get-the-result-of-command-substitution-without-using-stdio-and-stderr%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown

























1 Answer
1






active

oldest

votes








1 Answer
1






active

oldest

votes









active

oldest

votes






active

oldest

votes









1














This will save the last line of output:



path=$(whatever | tail -n 1)


If you need all the output to be utilized in some way:





  • use tee to print the output to the tty



    path=$(whatever | tee /dev/tty | tail -n 1)



  • or to save it



    path=$(whatever | tee ./file | tail -n 1)



  • or to process it (and print to the tty or a file, not to stdout which feeds the variable)



    path=$(whatever | tee >(grep foo | wc -c >/dev/tty) | tail -n 1)



  • You can even send (fork) the output to many destinations:



    path=$(whatever | tee /dev/tty ./file /some/named/fifo >(tool1) | tail -n 1)



Obviously a newline within the echoed path will break the solution.





If you can modify the final echo command in the user-provided script then please see this answer of mine for an approach that uses temporary files.






share|improve this answer























  • It works if I want it to go to the terminal, but what if the stdout is redirected somewhere? I have a test.sh: path=$((echo "doing something..." && echo "path") | tee /dev/tty | tail -1) && echo $path > result If I call it with ./test.sh > log.txt, it still outputs to the terminal. Is there any way to support this? I'd like to have both lines in the log.txt, and only the "path" in the result.
    – sashee
    Dec 13 at 11:58












  • Thank you, that link was a good guidance, I decided to go on the tempfile approach. This is the script I came up with: function dosth () { echo "doing something..."; echo "path" >$1; }; result_tmp=$(mktemp); trap 'rm $result_tmp' EXIT; dosth $result_tmp; path=$(cat $result_tmp); echo path > result
    – sashee
    Dec 13 at 14:08
















1














This will save the last line of output:



path=$(whatever | tail -n 1)


If you need all the output to be utilized in some way:





  • use tee to print the output to the tty



    path=$(whatever | tee /dev/tty | tail -n 1)



  • or to save it



    path=$(whatever | tee ./file | tail -n 1)



  • or to process it (and print to the tty or a file, not to stdout which feeds the variable)



    path=$(whatever | tee >(grep foo | wc -c >/dev/tty) | tail -n 1)



  • You can even send (fork) the output to many destinations:



    path=$(whatever | tee /dev/tty ./file /some/named/fifo >(tool1) | tail -n 1)



Obviously a newline within the echoed path will break the solution.





If you can modify the final echo command in the user-provided script then please see this answer of mine for an approach that uses temporary files.






share|improve this answer























  • It works if I want it to go to the terminal, but what if the stdout is redirected somewhere? I have a test.sh: path=$((echo "doing something..." && echo "path") | tee /dev/tty | tail -1) && echo $path > result If I call it with ./test.sh > log.txt, it still outputs to the terminal. Is there any way to support this? I'd like to have both lines in the log.txt, and only the "path" in the result.
    – sashee
    Dec 13 at 11:58












  • Thank you, that link was a good guidance, I decided to go on the tempfile approach. This is the script I came up with: function dosth () { echo "doing something..."; echo "path" >$1; }; result_tmp=$(mktemp); trap 'rm $result_tmp' EXIT; dosth $result_tmp; path=$(cat $result_tmp); echo path > result
    – sashee
    Dec 13 at 14:08














1












1








1






This will save the last line of output:



path=$(whatever | tail -n 1)


If you need all the output to be utilized in some way:





  • use tee to print the output to the tty



    path=$(whatever | tee /dev/tty | tail -n 1)



  • or to save it



    path=$(whatever | tee ./file | tail -n 1)



  • or to process it (and print to the tty or a file, not to stdout which feeds the variable)



    path=$(whatever | tee >(grep foo | wc -c >/dev/tty) | tail -n 1)



  • You can even send (fork) the output to many destinations:



    path=$(whatever | tee /dev/tty ./file /some/named/fifo >(tool1) | tail -n 1)



Obviously a newline within the echoed path will break the solution.





If you can modify the final echo command in the user-provided script then please see this answer of mine for an approach that uses temporary files.






share|improve this answer














This will save the last line of output:



path=$(whatever | tail -n 1)


If you need all the output to be utilized in some way:





  • use tee to print the output to the tty



    path=$(whatever | tee /dev/tty | tail -n 1)



  • or to save it



    path=$(whatever | tee ./file | tail -n 1)



  • or to process it (and print to the tty or a file, not to stdout which feeds the variable)



    path=$(whatever | tee >(grep foo | wc -c >/dev/tty) | tail -n 1)



  • You can even send (fork) the output to many destinations:



    path=$(whatever | tee /dev/tty ./file /some/named/fifo >(tool1) | tail -n 1)



Obviously a newline within the echoed path will break the solution.





If you can modify the final echo command in the user-provided script then please see this answer of mine for an approach that uses temporary files.







share|improve this answer














share|improve this answer



share|improve this answer








edited Dec 13 at 12:24

























answered Dec 13 at 11:49









Kamil Maciorowski

23.7k155074




23.7k155074












  • It works if I want it to go to the terminal, but what if the stdout is redirected somewhere? I have a test.sh: path=$((echo "doing something..." && echo "path") | tee /dev/tty | tail -1) && echo $path > result If I call it with ./test.sh > log.txt, it still outputs to the terminal. Is there any way to support this? I'd like to have both lines in the log.txt, and only the "path" in the result.
    – sashee
    Dec 13 at 11:58












  • Thank you, that link was a good guidance, I decided to go on the tempfile approach. This is the script I came up with: function dosth () { echo "doing something..."; echo "path" >$1; }; result_tmp=$(mktemp); trap 'rm $result_tmp' EXIT; dosth $result_tmp; path=$(cat $result_tmp); echo path > result
    – sashee
    Dec 13 at 14:08


















  • It works if I want it to go to the terminal, but what if the stdout is redirected somewhere? I have a test.sh: path=$((echo "doing something..." && echo "path") | tee /dev/tty | tail -1) && echo $path > result If I call it with ./test.sh > log.txt, it still outputs to the terminal. Is there any way to support this? I'd like to have both lines in the log.txt, and only the "path" in the result.
    – sashee
    Dec 13 at 11:58












  • Thank you, that link was a good guidance, I decided to go on the tempfile approach. This is the script I came up with: function dosth () { echo "doing something..."; echo "path" >$1; }; result_tmp=$(mktemp); trap 'rm $result_tmp' EXIT; dosth $result_tmp; path=$(cat $result_tmp); echo path > result
    – sashee
    Dec 13 at 14:08
















It works if I want it to go to the terminal, but what if the stdout is redirected somewhere? I have a test.sh: path=$((echo "doing something..." && echo "path") | tee /dev/tty | tail -1) && echo $path > result If I call it with ./test.sh > log.txt, it still outputs to the terminal. Is there any way to support this? I'd like to have both lines in the log.txt, and only the "path" in the result.
– sashee
Dec 13 at 11:58






It works if I want it to go to the terminal, but what if the stdout is redirected somewhere? I have a test.sh: path=$((echo "doing something..." && echo "path") | tee /dev/tty | tail -1) && echo $path > result If I call it with ./test.sh > log.txt, it still outputs to the terminal. Is there any way to support this? I'd like to have both lines in the log.txt, and only the "path" in the result.
– sashee
Dec 13 at 11:58














Thank you, that link was a good guidance, I decided to go on the tempfile approach. This is the script I came up with: function dosth () { echo "doing something..."; echo "path" >$1; }; result_tmp=$(mktemp); trap 'rm $result_tmp' EXIT; dosth $result_tmp; path=$(cat $result_tmp); echo path > result
– sashee
Dec 13 at 14:08




Thank you, that link was a good guidance, I decided to go on the tempfile approach. This is the script I came up with: function dosth () { echo "doing something..."; echo "path" >$1; }; result_tmp=$(mktemp); trap 'rm $result_tmp' EXIT; dosth $result_tmp; path=$(cat $result_tmp); echo path > result
– sashee
Dec 13 at 14:08


















draft saved

draft discarded




















































Thanks for contributing an answer to Super User!


  • 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.





Some of your past answers have not been well-received, and you're in danger of being blocked from answering.


Please pay close attention to the following guidance:


  • 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%2fsuperuser.com%2fquestions%2f1383268%2fhow-to-get-the-result-of-command-substitution-without-using-stdio-and-stderr%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

How do I know what Microsoft account the skydrive app is syncing to?

When does type information flow backwards in C++?

Grease: Live!