How to check if multiple variables are defined or not in bash - bash

I want to check, if multiple variable are set or not, if set then only execute the script code, otherwise exit.
something like:
if [ ! $DB=="" && $HOST=="" && $DATE=="" ]; then
echo "you did not set any variable"
exit 1;
else
echo "You are good to go"
fi

You can use -z to test whether a variable is unset or empty:
if [[ -z $DB || -z $HOST || -z $DATE ]]; then
echo 'one or more variables are undefined'
exit 1
fi
echo "You are good to go"
As you have used the bash tag, I've used an extended test [[, which means that I don't need to use quotes around my variables. I'm assuming that you need all three variables to be defined in order to continue. The exit in the if branch means that the else is superfluous.
The standard way to do it in any POSIX-compliant shell would be like this:
if [ -z "$DB" ] || [ -z "$HOST" ] || [ -z "$DATE" ]; then
echo 'one or more variables are undefined'
exit 1
fi
The important differences here are that each variable check goes inside a separate test and that double quotes are used around each parameter expansion.

If you are ok with writing a function for this purpose, it can be pretty convenient.
This solution uses the ${!VAR_NAME} syntax to check whether the variable is empty and has the added benefit of telling you which variable names are empty.
check_vars()
{
var_names=("$#")
for var_name in "${var_names[#]}"; do
[ -z "${!var_name}" ] && echo "$var_name is unset." && var_unset=true
done
[ -n "$var_unset" ] && exit 1
return 0
}
# Usage for this case
check_vars DB HOST DATE
echo "You are good to go"

I wound up using variable-variables to loop through an easily managed HEREDOC list of variable names:
# Ensure non-empty values.
# Loop through HEREDOC, test variable-variable isn't blank.
while read var; do
[ -z "${!var}" ] && { echo "$var is empty or not set. Exiting.."; exit 1; }
done << EOF
KUBE_NAMESPACE
DOCKER_REGISTRY
DOCKER_DEPLOY_USER
DOCKER_DEPLOY_PASSWORD
DOCKER_DEPLOY_EMAIL
EOF

You can check it also by put the variables name in a file
DB=myDB
HOST=myDB
DATE=myDATE
then test them if currently empty or unset
#!/bin/bash
while read -r line; do
var=`echo $line | cut -d '=' -f1`
test=$(echo $var)
if [ -z "$(test)" ]; then
echo 'one or more variables are undefined'
exit 1
fi
done <var.txt
echo "You are good to go"

Nice solution from #joe.still !
improvement is to exit after checking all variables
i=0
while read var; do
[ -z "${!var}" ] && { echo "$var is empty or not set. Exiting.."; let i=i+1; }
done << EOF
KUBE_NAMESPACE
DOCKER_REGISTRY
DOCKER_DEPLOY_USER
DOCKER_DEPLOY_PASSWORD
DOCKER_DEPLOY_EMAIL
EOF
if [ $i -gt 0 ]; then
echo $i
echo "exiting"
exit 1
fi

Good Day Everyone.
I've personally used this method in my bash scripts. Verified works on bash 4.4 and later in Ubuntu, openSUSE, and ClearLinux.
Can RHEL|CentOS|Alma and Arch Based users let me know it it works fine for you?
( [ "$VAR1""$VAR2""$VAR3""$VAR4""$VAR5" ] && echo -e " Warning: StackIsNotClear" ) || { echo -e " GoodNews: StackIsClear"; }

Related

Checking if the string is in proper format in Shell Scripting

I am trying to check if the string is in format in shell script.
below is the code i am trying and the output i want to get.
Format: <datatype>(length,length) | <datatype>(length,length)
I have multiple cases with this scenario, if both datatypes have () then it should show pass, else fail.
Eg. decimal(1,0)|number(11,0) this should pass but int|number(11,0) or decimal(1,0)|int should fail.
Code1:
INPUT='decimal(1,0)|number(11,0)'
sub="[A-Z][a-z]['!##$ %^&*()_+'][0-9][|][A-Z][a-z]['!##$ %^&*()_+'][0-9][|]"
if [ "$INPUT" == "$sub" ]; then
echo "Passed"
else
echo "No"
fi
Code 2:
INPUT='decimal(1,0)|number(11,0)'
sub="decimal"
if [ "$INPUT" == *"("*") |"*"("*") " ]; then
echo "Passed"
else
echo "No"
fi
Any help will be fine. Also note, I am very new to shell scripting.
Reading both values into variables, first removing alpha characters and then checking variables are not empty
result='FAIL'
input='int|number(6,10)'
IFS="|" read val1 val2 <<<"$(tr -d '[:alpha:]' <<<"$input")"
if [ -n "$val1" ] && [ -n "$val2" ]; then
result='PASS'
fi
echo "$result: val1='$val1' val2='$val2'"
Result:
FAIL: val1='' val2='(6,10)'
For input='decimal(8,9)|number(6,10)'
PASS: val1='(8,9)' val2='(6,10)'
That looks like just a simple regex to write.
INPUT='decimal(1,0)|number(11,0)'
if printf "%s" "$INPUT" | grep -qEx '[a-z]+\([0-9]+,[0-9]+\)(\|[a-z]+\([0-9]+,[0-9]+\))*'; then
echo "Passed"
else
echo "No"
fi

bash scripting one line shortcut for if test

Is there a shortcut (ie all on one line) for doing the following?
if [ -z "$PASSWORD" ] ; then
echo "PASSWORD envvar required. Exiting..."
exit 1
fi
I'm thinking along the lines of the following. Or maybe there's an even shorter way.
[ -z "$PASSWORD" ] && ...
That is, how do put the echo then exit after the &&
You can do it like this:
[ -z "$PASSWORD" ] && { echo "PASSWORD envvar required. Exiting..."; exit 1; }
Note the extra ; at the end of the line before the }, this is necessary and you cannot leave it out.
It's called a command group.
[[ -z "$PASSWORD" ]] && echo "PASSWORD envvar required. Exiting." && exit 1
Your single brackets will work fine. Consider learning to use the doubles, though.

Bash - Check of multiple environment variables and list all missing

I'm working on a few scripts where I need to check for a few environment variables and list all the ones missing. I'm seeing a lot of posts where it would check for one and exit.
if [ -z "$BLAH" ]; then
echo "Missing BLAH"
exit 1
fi
However, I would like to print all the missing ones and then exit if anything is not set. I'm doing something like this right now, Is there any more elegant way to do this?
function check_env_vars {
status=0
for name in $*; do
value="${!name}"
echo "$value"
if [[ -z "$value" ]]; then
echo "$name environment variable must not be empty"
status=1
fi
done
return $status
}
if [[ check_env_vars "BLAH" "BLAH1" "BLAH2" -ne 0 ]]; then
exit 1
fi
Appreciate any thoughts or ideas.
if already checks the exit status; that's what it does with [[ ... ]] in the first place.
if ! check_env_vars "BLAH" "BLAH1" "BLAH2"; then
exit 1
fi
That said, bash already has syntax for verifying that a variable is set and non-null:
check_vars () {
for name; do
: ${!name:?$name must not be empty}
done
}

bash determine if variable is empty and if so exit.

I am trying to perform this:
i have a test file which md5sum of files located on sftp.
variables should contain an md5sum (string), if the variable is empty it means there is no file on the sftp server.
i am trying this code but it does not work..
if [ -z $I_IDOCMD5 ] || [ -z $I_LEGALMD5 ] || [ -z $I_ZIPMD5 ]
then
echo "ERROR: At least one file not present of checksum missing no files will be deleted" >>$IN_LOG
ERRORS=$ERRORS+2
else
if [[ $I_IDOCMD5 == $($DIGEST -a md5 $SAPFOLDER/inward/idoc/$I_IDOC) ]]
then
echo "rm IDOC/$I_IDOC" >/SAP/commands_sftp.in
else
echo "problem with checksum"
ERRORS=$ERRORS+2
fi
if [[ $I_LEGALMD5 == $($DIGEST -a md5 $SAPFOLDER/inward/legal/$I_LEGAL) ]]
then
echo "rm LEGAL/$I_LEGAL" >>/SAP/commands_sftp.in
else
echo "problem with checksum"
ERRORS=$ERRORS+2
fi
if [[ $I_ZIPMD5 == $($DIGEST -a md5 $SAPFOLDER/inward/zip/$I_ZIP) ]]
then
echo "rm ZIP/$I_ZIP" >>/SAP/commands_sftp.in
else
echo "problem with checksum"
ERRORS=$ERRORS+2
fi
The answer I prefer is following
[[ -z "$1" ]] && { echo "Parameter 1 is empty" ; exit 1; }
Note, don't forget the ; into the {} after each instruction
One way to check if a variable is empty is:
if [ "$var" = "" ]; then
# $var is empty
fi
Another, shorter alternative is this:
[ "$var" ] || # var is empty
In bash you can use set -u which causes bash to exit on failed parameter expansion.
From bash man (section about set builtin):
-u
Treat unset variables and parameters other than the special parameters "#" and "*" as an error when performing parameter
expansion. If expansion is attempted on an unset variable or
parameter, the shell prints an error message, and, if not interactive,
exits with a non-zero status.
For more information I recommend this article:
http://redsymbol.net/articles/unofficial-bash-strict-mode/
You can use a short form:
FNAME="$I_IDOCMD5"
: ${FNAME:="$I_LEGALMD5"}
: ${FNAME:="$I_ZIPMD5"}
: ${FNAME:?"Usage: $0 filename"}
In this case the script will exit if neither of the I_... variables is declared, printing an error message prepended with the shell script line that triggered the message.
See more on this in abs-guide (search for «Example 10-7»).
First test only this (just to narrow it down):
if [ -z "$I_IDOCMD5" ] || [ -z "$I_LEGALMD5" ] || [ -z "$I_ZIPMD5" ]
then
echo "one is missing"
else
echo "everything OK"
fi
echo "\"$I_IDOCMD5\""
echo "\"$I_LEGALMD5\""
echo "\"$I_ZIPMD5\""
"if the variable is empty it means there is no file on the sftp server"
If there is no file on the sftp server, is the variable then really empty ?
No hidden spaces or anything like that ? or the number zero (which counts as non-empty) ?

Bash, always echo in conditional statement

This may turn out to be more of a thought exercise, but I am trying to echo a newline after some command I'm executing within a conditional. For example, I have:
if ssh me#host [ -e $filename ] ; then
echo "File exists remotely"
else
echo "Does not exist remotely"
fi
And want to throw in an echo after the ssh command regardless of the outcome. The reason is formatting; that way a newline will exist after the prompt for password for ssh.
First Try
if ssh me#host [ -e $filename ] && echo ; then
Because && echo would not change the conditional outcome, but bash would not execute echo if ssh returned false. Similarly,
if ssh me#host [ -e $filename ] || (echo && false) ; then
Does not work because it will short-circuit if ssh returns true.
An answer to the problem would be
ssh me#host [ -e $filename ]
result=$?
echo
if [ $result == 0 ] ; then
but was wondering if there was some similar conditional expression to do this.
Thanks.
While this would work
if foo && echo || ! echo; then
I'd prefer putting the whole thing into a function
function addecho() {
"$#" # execute command passed as arguments (including parameters)
result= $? # store return value
echo
return $result # return stored result
}
if addecho foo; then
What about this?
if ssh me#host [ -e $filename ] && echo || echo; then
I have not thought about precedence order of && and || and surely putting some parenthesis would help, but like that it works already... you get the echo both when ssh fails and when it succeeds...
Add the "echo" before the filename test
if ssh me#host "echo; [ -e $filename ]"; then
echo "File exists remotely"
else
echo "Does not exist remotely"
fi

Resources