1

I'm trying to write an If condition as function and I'm not sure if this is even possible.

Following case:

File1

if_exit()
{
  if $1; then
      echo "$2"
      exit 1
  fi
}

File2

source File1

SUUSER=$(whoami)
if_exit "[ $SUUSER != 'root' ]" "Please run the script as root"

Explanation: I want to write a function, which includes If contitions (short example used here). Then I want to call that function with different things like mentioned above in the code example or:

if_exit "[ $(lsb_release -is) != 'Debian' ] && [ $(lsb_release -cs) != 'stretch' ]" "The script only works with Stretch"

Thanks in advance!

Aeris
  • 307
  • 5
  • 16

3 Answers3

2

I would refactor so that you don't have to use quoting around the arguments.

if_exit()
{
    local message=$1
    shift
    if "$@"; then
        echo "$0: $message" >&2
        exit 1
    fi
}

# Tangentially, don't use upper case for private variables
Suuser=$(whoami)
if_exit "Please run the script as root" [ "$Suuser" != 'root' ]

Notice also how we print diagnotics to standard error, and take care to include the name of the script which caused the diagnostic to be printed.

tripleee
  • 175,061
  • 34
  • 275
  • 318
  • So the function recieves the setence and stores it to message. After that you use shift to switch the other return value to the "left"? But how can I use your solution with a comparison like this? if_exit "Please run with Buster" [ $(lsb_release -is) != 'Debian' ] && [ $(lsb_release -cs) != 'stretch' ] And thats a good reminder with the variable names :P PS: Is that bad style to use such a construct to shorten the program code? Thanks in advance, that you anser my beginner queswtion :P! – Aeris Jan 12 '19 at 15:40
  • The argument can only be a simple command with this solution. For complex commands, I would go with `[ $(lsb_release -is) != 'Debian' ] && [ $(lsb_release -cs) != 'stretch' ] || die "Please run with Buster"` – tripleee Jan 12 '19 at 16:58
0

You would probably have to play around with eval to make this work the way you like, which is generally something you want to avoid at all cost. For your use case I would recommend:

function die() {
    echo "$1"
    exit 1
}

[ "$SUUSER" != 'root' ] && die "Please run the script as root"

[ "$(lsb_release -is)" != 'Debian' && "$(lsb_release -cs)" != 'stretch' ] && die "The script only works with Stretch"
Erik Dannenberg
  • 5,716
  • 2
  • 16
  • 21
  • For more variants of `die`, see also https://stackoverflow.com/questions/7868818/in-bash-is-there-an-equivalent-of-die-error-msg – tripleee Jan 12 '19 at 17:00
  • Why not use `echo "$@"` in the `die()` function? Ik will help those who are lazy with quotes. – Walter A Jan 12 '19 at 20:15
0

When you only have a small number of checks, you can use [[ $SUUSER != 'root' ]] && { echo "Please run the script as root"; echo exit 1; }

When you have a lot of checks, I would use a die() function like @erik_dannenberg wrote.

off-topic: You should write your own shell variables in lowercase, like ${su_user}.

One reason of your proposed function is the possibility of showing which test failed (compare "${su_user}" with root). When you want this, make a function like checkroot(). You will take a lot of responsibilities when you want to support all normal special characters.
I tried something with support of the [ ... ] syntax. Do you see what is wrong with this "solution"?

if_exit() { # incorrect function
   # skip first '['
   shift
   # split line around ]
   IFS="]" read -r testparams errormessage <<< "${@}"
   if [ ${testparams} ] ; then
      echo "Test [ ${testparams% } ] failed: ${errormessage# }"
      # exit 1
   fi
}

if_exit [ -f non_existing_file ] "file not existing"
su_user="root"
if_exit [ "${su_user}" \!= root ] "Please run the script as root"
echo "Another test with wrong user"
su_user="aeris"
if_exit [ "${su_user}" \!= root ] "Please run the script as root"

Looking good, except for the exclamation mark?
It will fail when su_user is empty or has spaces (su_user="I dont want to be tested" ).

You can make a work-around for this problem in the if_exit() function, but will continue to meet new problems (like spaces in the filename).
You can look for the source code of test.c, but you should drop your nice intentions and choose for another solution (die() or compare_strings()).

Walter A
  • 19,067
  • 2
  • 23
  • 43