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.
then on a separate line. 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. 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 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) 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. 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) 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)) command fails or not, I returned else part with exit 0 as well: command && (echo "OK"; exit 0) || (c=$?; echo "NOK"; (exit 0)) 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. #!/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