3

Sometimes there are two commands which I often invoke in a row. However the second command only makes sense in case the first command was successful.

I wanted to do something like this:

#!/bin/bash

if [ $? -gt 0 ]
then
    echo "WARNING: previous command entered at the shell prompt failed"
fi

But it doesn't work:

t@quad:~$ echo "abc" | grep def
t@quad:~$ ./warnme.sh 
Last command succeeded

What I'd like is something a bit like this:

t@quad:~$ echo "abc" | grep def
t@quad:~$ echo ${PIPESTATUS[1]}
1

Where we can clearly see that the last command failed.

The result I'd like to have:

t@quad:~$ echo "abc" | grep def
t@quad:~$ ./warnme.sh 
WARNING: previous command entered at the shell prompt failed

I can't find a way to do it.

3
  • A shell script is an entirely new shell, so a new call. Do you need it as a separate shell script, or is defining a function or an alias in your bashrc enough? Commented Jan 30, 2014 at 21:24
  • @Wrikken: I'd need it as a shell script. Is there a way, given the parent shell's PID (which is accessible), to access the parent shell's $? variable (the one holding the result of the last command?). Maybe this should be a new question? Commented Jan 31, 2014 at 1:32
  • Not to my knowledge, no.. You could add your requirement that it should be a shell script to your question explicitly, maybe someone more knowledgeable knows something, but I'm afraid the answer will be there is no practical way to do it. Commented Jan 31, 2014 at 9:17

3 Answers 3

4
command1 && command2

does exactly what you want: command 2 is executed only if command1 succeeds. For example you could do:

ls a.out && ./a.out

Then a.out would only be executed if it could be listed. I wikiblogged about this at http://www.linuxintro.org/wiki/%26%26

Sign up to request clarification or add additional context in comments.

Comments

2

One option is to put this just before the list of commands you want to execute only if the previous was successful:

set -e

This will exit the script if any of the commands following it return non-zero (usually a fail). You can switch it off again with:

set +e

Or if you'd prefer to switch it off for just one line you can just logical-OR the command with true:

mycommand || true

For a lot of my scripts I have set -e at the top of the script as a safety feature to prevent the script cascading and doing something dangerous.

Comments

1

How about:

echo "abc" | grep def || ./warnme.sh

Where warnme.sh is now only the warning without the test. It's only called if the first command fails.

In other words, it would be the same as:

echo "abc" | grep def || echo "WARNING: That didn't work..."

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.