How can I do something like this in bash?
if "`command` returns any error";
then
echo "Returned an error"
else
echo "Proceed..."
fi
How can I do something like this in bash?
if "`command` returns any error";
then
echo "Returned an error"
else
echo "Proceed..."
fi
How 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.
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.
– Raven
Mar 29 '22 at 07:16
if
statements should be used. But if needed you could run: command && (command1; command 2) || (command3; command 4)
– Dean Householder
Aug 16 '22 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.
– janmoesen
Oct 17 '11 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.
– tripleee
Nov 04 '16 at 12:34
if
? If the success branch is a no-op, so you'd only need if ! cmd; then error...
, as I understand, if
alone can't do the negation (bash doesn't seem to have a not
builtin), so one should resort to some [ ... ]
hackery then, right?
– Sz.
Aug 19 '19 at 15:51
if ! cmd
is fine. Otherwise, a common arrangement is to use an else
clause. You can't have an empty then
but you sometimes see then : nothing; else
where the :
no-op is significant. true
would work there as well.
– tripleee
Aug 19 '19 at 17:13
if ! cmd
is fine" ah thanks! (I did try, but I managed to get something obvious wrong then. I guess I only tried a not
, instead of just a !
.)
– Sz.
Aug 19 '19 at 17:34
result=$(command); if [ $? -eq 0 ]; then ...
. The gotcha here though is that if you declare
, local
or readonly
the var that you are assigning, then $?
will be the return value of the assignment command, not the command that you are interested in! (So declare the var first, then assign it).
– spikyjt
Mar 03 '20 at 13:47
if ! output=$(command); then ...
syntax.
– yurez
Jan 08 '21 at 11:05
cmd=( theCommand "with args" and "other args" "and so on"); if "${cmd[@]}"; then ...
-- I expecially like this because the array definition can include arbitrary whitespace so the options can be laid out with newlines for maximum readability.
– glenn jackman
Jan 07 '22 at 15:41
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)
command && echo "OK" || (c=$?; echo "NOK"; (exit $c))
?
– jrw32982
Apr 01 '15 at 18:24
echo "OK"
part could itself fail, then this is better: command && (echo "OK"; exit 0) || (c=$?; echo "NOK"; (exit $c))
– jrw32982
Apr 01 '15 at 18:34
command
fails or not, I returned else
part with exit 0
as well: command && (echo "OK"; exit 0) || (c=$?; echo "NOK"; (exit 0))
– Qumber
Jun 16 '20 at 09:36
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.
– Stéphane Chazelas
Apr 01 '15 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
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
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
then
on a separate line. – l0b0 Oct 17 '11 at 09:00command``returns a sane return value. Today most do, but e.g.
vi(1)` (the original one) was (in)famous for its random return values. – vonbrand Dec 27 '15 at 21:02vi
. – Keith Thompson Dec 27 '15 at 22:03|
or lists;
,&
,&&
,||
) betweenif
andthen
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 oflogger
) and if the construct is in a place of a command (as in your example) then the substitued output is executed as a command. – pabouk - Ukraine stay strong Dec 15 '17 at 09:20command
? A simple example would help this answer a lot. Doescommand
need to be in backticks? A subprocess$(command)
? Quoted single/double? Etc? – David Parks Jun 21 '18 at 20:00command
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
– Keith Thompson Jun 21 '18 at 20:07[[ $("command-ffs") ]]
or something along those lines :D – OZZIE Feb 20 '19 at 08:04if foo=$(./return_1); then echo Y; else echo N; fi
returnsN
. (Assuming you have a script that returns a1
). – Dean Householder Aug 16 '22 at 19:32pipefail
is disabled by default. – Keith Thompson May 17 '23 at 20:38