How to get the result of command substitution without using stdio and stderr?
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
add a comment |
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
Having a "separate stream for the result" is exactly what stdout is (as distinct from stderr).
– Gordon Davisson
Dec 13 at 17:14
add a comment |
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
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
bash
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
add a comment |
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
add a comment |
1 Answer
1
active
oldest
votes
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.
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
add a comment |
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
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
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.
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
add a comment |
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.
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
add a comment |
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.
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.
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
add a comment |
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
add a comment |
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.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
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
Having a "separate stream for the result" is exactly what stdout is (as distinct from stderr).
– Gordon Davisson
Dec 13 at 17:14