Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to get output of a bash command in a variable

I have been following through some of the similar questions (such as How to set a variable to the output from a command in Bash?), however the accepted answers seem to be non-working for me. I wasn't sure whether I ought to derail someone else's question or post my own duplicate, so apologies if I chose wrong here.

I wish to get the output and exit status of a number of commands in a script I am putting together. Here is an example of what I have been using:

cmd_output=$(rm $file)
exit_status=$?
if [ "${exit_status}" -eq 0 ]
then
log "Successfully removed the original" ${TAB_LEVEL}
else
fail "Failed to remove the original, the output was: \n ${cmd_output}"
fi

The log and fail functions are:

# Usage: fail "Failure message"
function fail {
echo "FATAL ERROR: $1" >> "${LOG_DIR}/${LOG_FILE}"
exit 1
}

# Usage: log "Log message" 3    Where the tab-level is 3.
function log {
if (("${2}" > 0))
then
eval "printf '    %.0s' {1..$2}" >> "${LOG_DIR}/${LOG_FILE}"
fi
echo "$1" >> "${LOG_DIR}/${LOG_FILE}"
return 0
}

In the example above I use the $(cmd) format, but I have also tried using backticks.

In my log file, all I see when there is a failure is:

FATAL ERROR: Failed to remove the original, the output was: \n

Also, the output of the failed commands ends up on screen as per usual. Is there a common reason that my cmd_output variables would be remaining empty?

like image 277
Chris O'Kelly Avatar asked Oct 05 '12 01:10

Chris O'Kelly


People also ask

How do you store a command output in a variable?

To store the output of a command in a variable, you can use the shell command substitution feature in the forms below: variable_name=$(command) variable_name=$(command [option ...] arg1 arg2 ...) OR variable_name='command' variable_name='command [option ...]

How do you echo the output of a command?

The echo command writes text to standard output (stdout). The syntax of using the echo command is pretty straightforward: echo [OPTIONS] STRING... Some common usages of the echo command are piping shell variable to other commands, writing text to stdout in a shell script, and redirecting text to a file.

Which command should I use to display a variable?

The echo command is useful to display the variable's output especially when you know the content of a variable will not cause any issue.


2 Answers

You have to include the output of the special standard error output stream:

cmd_output=$(rm "$file" 2>&1)

There are three default streams on every program (that are numbered file descriptors):

0. Standard input (where the program normally reads from)
1. Standard output (where the program normally writes to)
2. Standard error (where the program normally writes error messages)

So to capture the error messages, we must redirect standard error output (stderr) into normal standard output (stdout) which will then be captured by the $(...) expression.

The syntax for redirection is through the > "operator". Immediately before it you tell which file descriptor to redirect (the default is 1, which is stdout). And you can specify it to redirect to a file. If you write an ampersand (&) after it, you force it to redirect into another file descriptor. Therefore, in this example, we redirect file descriptor 2 (stderr) into file descriptor 1 (stdout).

Also, you can also redirect input with < "operator", but in this case the default file descriptor is 0 (stdin).

Another observation is that it is probably good practice to place your $file variable between double quotes, in case it has white space characters.

Hope this helps a little =)

like image 199
Janito Vaqueiro Ferreira Filho Avatar answered Sep 29 '22 13:09

Janito Vaqueiro Ferreira Filho


*nix command generally have two forms of output: standard output (stdout) and standard error (stderr).

FOO=$(...) only captures stdout, and leaves stderr unhindered.

If you want the contents of stderr with this syntax, you need to postfix your command with 2>&1 so that stderr is merged into stdout. (e.g. like so: rm $file 2>&1)

like image 40
antak Avatar answered Sep 29 '22 11:09

antak