IF condition in bash - bash

I have just started learning to write bash scripts. This a simplified form of what I want to write.
The problem is despite of the input, it prints only "YES".
#! /usr/bin/bash
read input
if (("$input"== "y" || "$input" == "Y"))
then
echo "YES";
elif (("$input" == "n" || "$input" == "N"))
then
echo "NO";
else
echo "Not a valid input!!"
fi

Use [[ instead of (( like,
if [[ "$input" == "y" || "$input" == "Y" ]]
and also there must be a space exists before == operator.
ie,
input="n"
if [[ "$input" == "y" || "$input" == "Y" ]]
then
echo "YES";
elif [[ "$input" == "n" || "$input" == "N" ]]
then
echo "NO";
else
echo "Not a valid input!!"
fi
You could use regular expression also for condition checking purpose.
if [[ "$input" =~ ^[yY]$ ]]
then
echo "YES";
elif [[ "$input" =~ ^[nN]$ ]]
then
echo "NO";
else
echo "Not a valid input!!"
fi

When you automaticly convert the input to lowercase (using typeset), you do not have to bother with the the uppercases.
When you use an elif, always think 10 seconds for another solution. In this case you might want to use a "switch", in shell written as a case-statement:
#!/usr/bin/bash
typeset -l input
read input
case ${input} in
"y") echo "Yes";;
"n") echo "NO";;
*) echo "Not a valid input!!";;
esac

Related

Continue while loop in Bash Script even if a condition fails

#!/bin/bash
var="true"
i=1
while $var
do
read -p "Enter value (true/false): " var
if [[ $var == "true" ]]
then
echo "Iteration : $i"
((i++))
elif [[ $var == "false" ]]
then
echo "Exiting the process"
elif [[ $? -eq 1 ]]
then
echo "Invalid Choice."
echo "Avaialable Choices are true or false"
exit
fi
done
Script is Working Fine. I Enter true the loop will iterate for false the script stops.
I want the script will continue asking "Enter Value" if any other value instead of true or false will be entered.
This would do the same with a more academic syntax:
i=0
while :; do
printf 'Enter value (true/false): '
read -r var
case $var in
true)
i=$((i + 1))
printf 'Iteration : %d\n' $i
;;
false)
printf 'Exiting the process\n'
break
;;
*)
printf 'Invalid Choice.\nAvaialable Choices are true or false\n'
;;
esac
done
You might find this to be a cleaner solution:
i=0
while true; do
read -p "enter value: " myinput
if [[ $myinput = true ]]; then
echo "iteration $i"
i=$((i+1))
elif [[ $myinput = false ]]; then
echo "exiting"
exit
else
echo "invalid input"
fi;
done;
The issue I see with your current code is that it is unclear which command's exit status $? refers to. Does it refer to the echo in the previous elif block? Or the last condition check? Or something else entirely?
I'm new in bash. I tried that:
#!/bin/bash
i=1
while [[ $var != "false" ]]
do
read -p "Enter value (true/false): " var
if [[ $var == "true" ]]
then
echo "Iteration : $i"
((i++))
elif [[ $var == "false" ]]
then
echo "Exiting the process"
elif [[ $? -eq 1 ]]
then
echo "Invalid Choice."
echo "Avaialable Choices are true or false"
fi
done
I changed while $var with while [[ $var ]] because while works like if. It runs the given command. In there it is $var's value.
And I moved exit to first elif expression's end. So if user type false program will exit.

How Can I Create a Bash Script For Menu Based LUKS Encryption?

I am writing a Bash script to make LUKS encryption user friendly and to make the process faster while still allowing control of the arguments.
My current code:
#!/usr/bin/env bash
## Ask user for device.
echo "Device:"
read device
## Ask user for cipher.
echo "Available ciphers:"
echo "AES [0]"
echo "Serpent [1]"
echo "Twofish [2]"
echo "Cipher:"
read cipherin
if [[ $cipherin == "0" ]]; then
[[ $cipher == "aes-xts-plain64" ]]
elif [[ $cipherin == "1" ]]; then
[[ $cipher == "serpent-xts-plain64" ]]
elif [[ $cipherin == "2" ]]; then
[[ $cipher == "twofish-xts-plain64" ]]
else echo "Invalid choice."
fi
## Ask user for key length.
echo "Available key lengths (bits):"
echo "128 [0]"
echo "256 [1]"
echo "Key length:"
read keyin
if [[ $keyin == "0" ]]; then
[[ $key == "256" ]]
elif [[ $keyin == "1" ]]; then
[[ $key == "512" ]]
else echo "Invalid choice."
fi
## Ask user for hash.
echo "Available hashes:"
echo "SHA-1 [0]"
echo "SHA-256 [1]"
echo "SHA-512 [2]"
echo "Whirlpool [3]:"
echo "Hash:"
read hashin
if [[ $hashin == "0" ]]; then
[[ $hash == "sha1" ]]
elif [[ $hashin == "1" ]]; then
[[ $hash == "sha256" ]]
elif [[ $hashin == "2" ]]; then
[[ $hash == "sha512" ]]
elif [[ $hashin == "3" ]]; then
[[ $hash == "whirlpool" ]]
else echo "Invalid choice."
fi
## Ask user for PBKDF.
echo "Available PBKDFs:"
echo "argon2i [0]"
echo "argon2id [1]"
echo "pbkdf2 [2]"
read pbkdfin
if [[ $pbkdfin == "0" ]]; then
[[ $pbkdf == "argon2i" ]]
elif [[ $pbkdfin == "1" ]]; then
[[ $pbkdf == "argon2id" ]]
elif [[ $pbkdfin == "2" ]]; then
[[ $pbkdf == "pbkdf2" ]]
else echo "Invalid choice."
fi
## Ask user for iteration time.
echo "Iteration time (ms):"
read iteration
## Encrypt drive using LUKS.
echo "Encrypting..."
sudo cryptsetup --type luks2 -c ${cipher} -h ${hash}\
-i ${iteration} -s ${key} --pbkdf ${pbkdf} --use-urandom\
-y luksFormat ${device}
The command fails with "cryptsetup: invalid numeric value". I enter 2000 into the iterations, which is default, so I know the number of interations is not the issue.
I have used https://shellcheck.net with no positive outcome; I am confused by the results.

Bash Script : Check if number starts with

$var=1545334345
The $var is dynamic. How do I check if it starts with 15? I tried:
if [[ $var == 15* ]]; then
echo "Yes"
fi
and
if (( $var -eq 15* )); then
echo "Yes"
fi
Neither works.
Remove the $ from the assignment.
var=1545334345
The first if statement you wrote is correct.
if [[ $var == 15* ]]; then
echo "Yes"
fi

Unix scripting whoami/$USER not working as desired

Hi I have the script as below.
if [[ 'whoami' -eq "test" ]]; then
echo "test user"
else
echo "Not a test user"
fi
This is returning test user even if my user is not text. It would be great if someone can pin point my silly mistake.
-eq is for integer testing.
e.g.:
kent$ [[ "a" -eq "b" ]] && echo "y" || echo "n"
y
kent$ [[ 34 -eq 35 ]] && echo "y" || echo "n"
n
try:
kent$ [[ "a" == "b" ]] && echo "y" || echo "n"
n
You are using single quotes in place of backticks:
if [[ `whoami` -eq "test" ]]; then # Not 'whoami'
For improved readability (and easier nesting, if applicable), use
if [[ $(whoami) -eq "test" ]]; then
instead.
Just like this:
if [[ `whoami` == "test" ]]; then # Not 'whoami' -eq
echo "test user"
else
echo "Not a test user"
fi
don't use single quote and '-eq'

case or If string contains word1 and word2

In this example I want it to know if $# contains two words/symbols "load" and "/"
for one word/symbol this works
case "$#" in */*)
;;
echo "going to do stuff"
*)
echo "will do something else"
;;
esac
or
string='My string';
if [[ "$string" == *My* ]]
then
echo "It's there!";
fi
But if two words/symbols appear at random places I cant figure out how to do it.
Update:
The input will the module command. In this case I want to know if it is the module load with or without / that indicate version. the command will look like this
1) module load appname/1.1.1 or
2) module load appname
3) module (not load) (list, avail etc)
It is number 1 I am interested in for now.
3 will in some cases be variation of 1.
2 will be run as is but will include a message to the user
The slow way would be to iterate through the array twice and then check if both "load" and "/" were present, like this:
for element in $#; do [[ "$element" == "load" ]] && loadPresent=1; done
for element in $#; do [[ "$element" =~ ".*/.*" ]] && slashPresent=1; done
if [[ $loadPresent == 1 ]] && [[ $slashPresent == 1 ]]; then
echo "Contains load and /"
fi
(As I interpreted your question you want one parameter to be exactly "load" and another one to contain a slash.)
Something like this is possible:
if [[ ${#} =~ .*/.* && ${#} =~ ((^)|([ ]))load(($)|([ ])) ]]
then
echo both
fi
-or-
if LOAD=0 && SLASH=0 && \
for ARG in ${#};
do
if [ "${ARG#*/}" != "${ARG}" ]; then SLASH=1; fi
if [ "${ARG}" = "load" ]; then LOAD=1; fi
done && [ "${LOAD}${SLASH}" = "11" ];
then
echo both
fi
-or-
function loadslash()
{
LOAD=0 && SLASH=0
for ARG in ${#};
do
if [ "${ARG#*/}" != "${ARG}" ]; then SLASH=1; fi
if [ "${ARG}" = "load" ]; then LOAD=1; fi
done
test "${LOAD}${SLASH}" = "11"
}
if loadslash ${#}
then
echo both
fi
this will satisfy your requirements
if [[ $1 == "load" ]]; then
if [[ $2 == */* ]]; then
do first case
else
do second case
fi
else
do third case
fi

Resources