bash:output:get_the_output_of_a_command
Differences
This shows you the differences between two versions of the page.
Both sides previous revisionPrevious revisionNext revision | Previous revision | ||
bash:output:get_the_output_of_a_command [2021/01/26 15:00] – peter | bash:output:get_the_output_of_a_command [2021/01/26 15:07] (current) – peter | ||
---|---|---|---|
Line 1: | Line 1: | ||
====== BASH - Output - Get the output of a command ====== | ====== BASH - Output - Get the output of a command ====== | ||
+ | |||
+ | This depends on whether you want to store the command' | ||
+ | |||
+ | ---- | ||
+ | |||
+ | ===== Capture the output of a command ===== | ||
+ | |||
+ | To capture the output, you use command substitution: | ||
+ | |||
+ | <code bash> | ||
+ | output=$(command) | ||
+ | output=$(command 2>& | ||
+ | </ | ||
+ | |||
+ | ---- | ||
+ | |||
+ | ===== To save both output of a command; and the exit status ===== | ||
+ | |||
+ | If you want both: | ||
+ | |||
+ | <code bash> | ||
+ | output=$(command) | ||
+ | status=$? | ||
+ | </ | ||
+ | |||
+ | The assignment to output has no effect on command' | ||
+ | |||
+ | ---- | ||
+ | |||
+ | ===== Capture stdout and take action on exit status ===== | ||
+ | |||
+ | If you want to capture stdout as well as taking action on success/ | ||
+ | |||
+ | <code bash> | ||
+ | if output=$(command); | ||
+ | printf "it succeeded\n" | ||
+ | ... | ||
+ | </ | ||
+ | |||
+ | ---- | ||
+ | |||
+ | ===== Capture stdout and stderr ===== | ||
+ | |||
+ | What you cannot do is capture stdout in one variable, and stderr in another, using only FD redirections. | ||
+ | |||
+ | You must use a temporary file (or a named pipe) to achieve that one. | ||
+ | |||
+ | Well, you can use a horrible hack like: | ||
+ | |||
+ | <code bash> | ||
+ | cmd() { curl -s -v http:// | ||
+ | |||
+ | result=$( | ||
+ | { stdout=$(cmd) ; } 2>&1 | ||
+ | printf "this line is the separator\n" | ||
+ | printf " | ||
+ | ) | ||
+ | var_out=${result# | ||
+ | var_err=${result%$' | ||
+ | </ | ||
+ | |||
+ | Obviously, this is not robust, because either the standard output or the standard error of the command could contain whatever separator string you employ. | ||
+ | |||
+ | And if you want the exit code of your cmd (here a modification in the case of if the cmd stdout nothing) | ||
+ | |||
+ | <code bash> | ||
+ | cmd() { curl -s -v http:// | ||
+ | |||
+ | result=$( | ||
+ | { stdout=$(cmd); | ||
+ | printf "this is the separator" | ||
+ | printf " | ||
+ | exit " | ||
+ | ) | ||
+ | returncode=$? | ||
+ | |||
+ | var_out=${result# | ||
+ | var_err=${result%this is the separator*} | ||
+ | </ | ||
+ | |||
+ | ---- | ||
+ | |||
+ | ===== Only keep stderr ===== | ||
+ | |||
+ | Say you want only the stderr, but not stdout. | ||
+ | |||
+ | Then first you have to decide where you do want stdout to go: | ||
+ | |||
+ | <code bash> | ||
+ | output=$(command 2>&1 >/ | ||
+ | output=$(command 2>&1 >/ | ||
+ | output=$(command 3>&2 2>&1 1>& | ||
+ | </ | ||
+ | |||
+ | Since the last example may seem a bit confusing, here is the explanation. | ||
+ | |||
+ | * First, keep in mind that **1>& | ||
+ | * So it will be easier to analyze the following sequence: $(... 3>&2 2>&1 1>&3 3>& | ||
+ | |||
+ | ^Redirection^fd 0 (stdin)^fd 1 (stdout)^fd 2 (stderr)^fd 3^Description^ | ||
+ | |initial|/ | ||
+ | |$(...)|/ | ||
+ | |3>& | ||
+ | |2>& | ||
+ | |1>& | ||
+ | |3>& | ||
+ | |||
+ | A little note: operation **n>& | ||
+ | |||
+ | This way what the script writes to FD 2 (normally stderr) will be written to stdout because of the second redirection. | ||
+ | |||
+ | It's possible, although considerably harder, to let stdout "fall through" | ||
+ | |||
+ | <code bash> | ||
+ | exec 3>& | ||
+ | output=$(command 2>&1 1>& | ||
+ | exec 3>& | ||
+ | |||
+ | # or this alternative, | ||
+ | { output=$(command 2>&1 1>& | ||
+ | </ | ||
+ | |||
+ | In the last example above, note that **1>& | ||
+ | |||
+ | ---- | ||
+ | |||
bash/output/get_the_output_of_a_command.1611673218.txt.gz · Last modified: 2021/01/26 15:00 by peter