How can I do something like this in bash?
if "`command` returns any error";
then
echo "Returned an error"
else
echo "Proceed..."
fi
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems. It only takes a minute to sign up.
Sign up to join this communityHow to conditionally do something if a command succeeded or failed
That's exactly what bash's if
statement does:
if command ; then
echo "Command succeeded"
else
echo "Command failed"
fi
Adding information from comments: you don't need to use the [
... ]
syntax in this case. [
is itself a command, very nearly equivalent to test
. It's probably the most common command to use in an if
, which can lead to the assumption that it's part of the shell's syntax. But if you want to test whether a command succeeded or not, use the command itself directly with if
, as shown above.
command``returns a sane return value. Today most do, but e.g.
vi(1)` (the original one) was (in)famous for its random return values.
|
or lists ;
, &
, &&
, ||
) between if
and then
you simply put them there like this: if ssh invalid | logger ; then echo "hi"; fi
--- If you really want to enclose the command list once more you can use the curly {}
or round ()
brackets. --- The construct $(ssh invalid | logger)
is replaced by the stdout output of the command(s) (in this case the output of logger
) and if the construct is in a place of a command (as in your example) then the substitued output is executed as a command.
Dec 15, 2017 at 9:20
command
is just any arbitrary command, just as if you typed it by itself at the shell prompt. No, it doesn't need to be in backticks or $(...)
; that would be replaced by the output of the command (unless you want to execute a command given by the output of another command). For example: if cmp -s file1 file2 ; then echo Same ; else echo Different ; fi
Jun 21, 2018 at 20:07
For small things that you want to happen if a shell command works, you can use the &&
construct:
rm -rf somedir && trace_output "Removed the directory"
Similarly for small things that you want to happen when a shell command fails, you can use ||
:
rm -rf somedir || exit_on_error "Failed to remove the directory"
Or both
rm -rf somedir && trace_output "Removed the directory" || exit_on_error "Failed to remove the directory"
It's probably unwise to do very much with these constructs, but they can on occasion make the flow of control a lot clearer.
&&
and ||
in the last example is important. If you reverse the order as in rm ... || command1 && command2
, you'll end up executing both commands in case rm
fails as here the &&
applies to command1
and assuming that doesn't fail as well, this will cause command2
to run. In the reverse order rm ... && command2 || command1
the double-excecution is not an issue, assuming command2
never fails.
if
statements should be used. But if needed you could run: command && (command1; command 2) || (command3; command 4)
Aug 16, 2022 at 19:39
Check the value of $?
, which contains the result of executing the most recent command/function:
#!/bin/bash
echo "this will work"
RESULT=$?
if [ $RESULT -eq 0 ]; then
echo success
else
echo failed
fi
if [ $RESULT == 0 ]; then
echo success 2
else
echo failed 2
fi
if
idiom. I prefer Keith Thompson's answer.
Oct 17, 2011 at 11:30
if
is to do this. The flow control conditions in Bash all examine $?
behind the scenes; that's what they do. Explicitly examining its value should be unnecessary in the vast majority of cases, and is usually a beginner antipattern.
This worked for me:
command && echo "OK" || echo "NOK"
if command
succeeds, then echo "OK"
is executed, and since it's successful, execution stops there. Otherwise, &&
is skipped, and echo "NOK"
is executed.
command && echo "OK" || c=$?; echo "NOK"; $(exit $c)
Jun 24, 2014 at 15:57
command && echo "OK" || (c=$?; echo "NOK"; (exit $c))
?
echo "OK"
part could itself fail, then this is better: command && (echo "OK"; exit 0) || (c=$?; echo "NOK"; (exit $c))
It should be noted that if...then...fi
and &&
/||
type of approach deals with exit status returned by command we want to test( 0 on success ); however, some commands don't return a non-zero exit status if command failed or couldn't deal with input. This means that the usual if
and &&
/||
approaches won't work for those particular commands.
For instance, on Linux GNU file
still exits with 0 if it received a non-existing file as argument and find
couldn't locate the file user specified.
$ find . -name "not_existing_file"
$ echo $?
0
$ file ./not_existing_file
./not_existing_file: cannot open `./not_existing_file' (No such file or directory)
$ echo $?
0
In such cases, one potential way we could handle the situation is by reading stderr
/stdin
messages, e.g. those that returned by file
command, or parse output of the command like in find
. For that purposes, case
statement could be used.
$ file ./doesntexist | while IFS= read -r output; do
> case "$output" in
> *"No such file or directory"*) printf "%s\n" "This will show up if failed";;
> *) printf "%s\n" "This will show up if succeeded" ;;
> esac
> done
This will show up if failed
$ find . -name "doesn'texist" | if ! read IFS= out; then echo "File not found"; fi
File not found
The most error prone I could come up with was:
RR=$?
Now, for not only this situation, but others you may face, consider:
$ AA=1 ; if (( "10#0${AA}" == 1 )) ; then echo yes ; else echo no ; fi
Answer: yes
$ AA=1 ; if (( "10#0${AA}" != 1 )) ; then echo yes ; else echo no ; fi
Answer: no
$ AA=1 ; if (( "10#0${BB}" == 1 )) ; then echo yes ; else echo no ; fi
Answer: no
$ AA=1 ; if (( "10#0${BB}" != 1 )) ; then echo yes ; else echo no ; fi
Answer: yes
$ AA=1 ; if (( "10#0${BB}" == 0 )) ; then echo yes ; else echo no ; fi
Answer: yes
This prevents all kinds off errors.
You are probably aware of all the syntax, but here some tips:
"blank"
to be nothing
.${variable}
.base-8
. You will get an error like:
value too great for base (error token is "08")
for numbers above 7
. That is when 10#
comes into play:10#
forces the number to be base-10
.You can do this:
if ($( ping 4.4.4.4 -c1 > /dev/null )) ; then
echo "ping response succsess!!!"
fi
ping
is captured in view of running it as a command. But because the output is redirected to /dev/null that will always be the empty string. So you're running nothing in a subshell, which means the previous exit status (of the command substitution subshell, that is of ping) will be retained. Obviously, the correct way is if ping ...; then
here.
Apr 1, 2015 at 15:40
#!/bin/bash
if command-1 ; then
echo "command-1 succeeded and now running from this block command-2"
command-2
else
echo "command-1 failed and now running from this block command-3"
command-3
fi
As noted elsewhere in this thread, the original question basically answers itself. Here is an illustration showing that if
conditions may also be nested.
This example uses if
to check if a file exists and if it is a regular file. If those conditions are true, then check whether or not it has a size greater than 0.
#!/bin/bash
echo "Which error log are you checking today? "
read answer
if [ -f /opt/logs/$answer*.errors ]
then
if [ -s /opt/logs/$answer*.errors ]
then
echo "Content is present in the $answer error log file."
else
echo "No errors are present in the $answer error log file."
fi
else
echo "$answer does not have an error log at this time."
fi
This could be done simply in this way as $?
gives you the status of last command executed.
So it could be
#!/bin/sh
... some command ...
if [ $? == 0 ] ; then
echo '<the output message you want to display>'
else
echo '<failure message>'
fi