Команда if status линукс

How to conditionally do something if a command succeeded or failed

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.

Careful, this presumes the 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.

@cgseller If you want to use multiple commands (like pipelines | 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.

@DavidParks: 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" 
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.

They are shorter and (at least in some shells) faster. I shudder remembering a monster Ultrix installation script written with just these conditional constructions I once tried to decipher.

It should be noted that the order of && 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.

It is also noteworthy to know that if you need multiple commands, you can chain items in a subshell. This is almost always going to result in a spaghetti code situation and regular if statements should be used. But if needed you could run: command && (command1; command 2) || (command3; command 4)

Читайте также:  Remove hidden directory linux

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 

While technically correct (and thus not warranting a downvote), it’s not making use of Bash’s if idiom. I prefer Keith Thompson’s answer.

There are benefits to this idiom — it preserves the return value. In all, I find this one to be more powerful, though more verbose. it’s also easier to read.

@Nowaker The fact that the sole purpose of 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.

I prefer this for readability. The main command is typically a really long one. Putting it inside an «if» statement makes for bad readability.

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.

If you want to do something if it fails, and preserve the exit code (to show in command prompt or test in a script), you can do this: command && echo «OK» || c=$?; echo «NOK»; $(exit $c)

Also, if the 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 

Источник

How to check the exit status using an ‘if’ statement

What would be the best way to check the exit status in an if statement in order to echo a specific output? I’m thinking of it being:

if [ $? -eq 1 ] then echo "blah blah blah" fi 

The issue I am also having is that the exit statement is before the if statement simply because it has to have that exit code. Also, I know I’m doing something wrong since the exit would obviously exit the program.

If you need to use the exit code from some particular program invocation in two different places, then you need to preserve it — something along the lines of some_program; rc=$?; if [ $ -eq 1 ] . fi ; exit $

Читайте также:  Linux применить настройки сети

12 Answers 12

Every command that runs has an exit status.

That check is looking at the exit status of the command that finished most recently before that line runs.

If you want your script to exit when that test returns true (the previous command failed) then you put exit 1 (or whatever) inside that if block after the echo .

That being said, if you are running the command and are wanting to test its output, using the following is often more straightforward.

if some_command; then echo command returned true else echo command returned some error fi 

Or to turn that around use ! for negation

if ! some_command; then echo command returned some error else echo command returned true fi 

Note though that neither of those cares what the error code is. If you know you only care about a specific error code then you need to check $? manually.

Источник

How to check if a command succeeded?

Prefer $(foo) over backticks `foo`, because you can nest it, and it’s easier to distinguish from apostrophes.

10 Answers 10

The return value is stored in $? . 0 indicates success, others indicates error.

some_command if [ $? -eq 0 ]; then echo OK else echo FAIL fi 

Like any other textual value, you can store it in a variable for future comparison:

some_command retval=$? do_something $retval if [ $retval -ne 0 ]; then echo "Return code was not zero but $retval" fi 

For possible comparison operators, see man test .

That’s nice . can i hold the output error . , because in this case i have 2 error : command error «text» ex, file not found and my error «text» Which is in this case failed for example

@Blauhirn [ $? ] (or equivalently, test $? ) does not work because $? evaluates to a number (0, 1, etc.) which is not null. See the docs for test : «If EXPRESSION is omitted, ‘test’ returns false. If EXPRESSION is a single argument, ‘test’ returns false if the argument is null and true otherwise.»

If you only need to know if the command succeeded or failed, don’t bother testing $? , just test the command directly. E.g.:

if some_command; then printf 'some_command succeeded\n' else printf 'some_command failed\n' fi 

And assigning the output to a variable doesn’t change the return value (well, unless it behaves differently when stdout isn’t a terminal of course).

if output=$(some_command); then printf 'some_command succeded, the output was «%s»\n' "$output" fi 

What if you want to do something other than branching like storing the boolean of whether it failed or not into a .ini? Then your output variable doesn’t do that, but $? does, so you’re incorrect in saying that testing the command directly is strictly better.

Assigning the output to a variable may change the return value when one uses local command, i.e. local foo=$(false); echo $?; produces 0 on the output. But local is only relevant inside of bash functions.

@Prometheus hard to say without seeing the code. Perhaps it incorrectly returns 0 in the case you considered a failure, or perhaps you added additional commands to the command substitution without using && between them.

I’m not used to bash scripting. Does the if require some brackets or anything? Can I just have. if cd unreliable_dir; then

command && echo OK || echo Failed 

If command writes errors out to stderr, you can use the form command 2> /dev/null && echo OK || echo Failed . The 2> /dev/null redirects stderr output to /dev/null . However, some utilities will write errors to stdout (even though this is bad practice). In this case you can omit the 2 from the redirection, but you will lose any output from the command. This method of checking success is good for simple ternary logic but for more complex behavior it’s best to check $? for command success, or use the if block method outlined in @geirha’s answer.

Читайте также:  Linux где мой компьютер

$? should contain the exit status of the previous command, which should be zero for no error.

cd /nonexistant if [ $? -ne 0 ] then echo failed else echo success! fi 

for most cases, it’s easier to use the && construct to chain commands that need to depend on each other. So cd /nonexistant && echo success! would not echo success because the command breaks before && . The corollary of this is || , where cd /nonexistant || echo fail would echo fail because cd failed (this becomes useful if you use something like ||exit , which will end the script if the previous command failed).

That’s nice . can i hold the output error . , because in this case i have 2 error : command error «text» ex, file not found and my error «text» Which is in this case failed for example

No, my line is correct, it gives the actual result code as a number regardless if success or failure.

Ok, please explain the differences of these to me: true && echo $? || echo $? / true; echo $? and false && echo $? || echo $? / false; echo $? — you’ll find, they do the exact same thing 😀

Yes, the same result but without the condition. The original question asked was «How to check if a command succeeded?», this was based on previous answers. I guess a better example would be: command && echo «success: $?» || echo «fail: $?»

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 

Источник

Оцените статью
Adblock
detector