Bash: multiple conditions in if to check a parameter - bash

So, to run my script I use a parameter like this:
./script 789
The parameter is to change the permissions of a file or a directory, and I'd like to check if every digit is between 0 and 7, so what I tried is the next thing:
if [[ ${1:0:1} -ge 0 && ${1:0:1} -le 7 ]] && [[ ${1:1:1} -ge 0 && ${1:1:1} -le 7]] && [[ ${1:2:1} -ge 0 && ${1:2:1} -le 7]]
then {go ahead with the code}
else
echo "Error: each digit in the parameter must be between 0 and 7"
fi
If it's true, then go ahead with the script, else show an error message, but it doesn't seem to work.

You want to match the parameter with the regex [0-7][0-7][0-7], or [0-7]{3}. In bash, you can do:
[[ "$1" =~ [0-7]{3} ]] || { echo 'invalid parameter' >&2; exit 1; }
Or:
echo "$1" | grep -Eq '[0-7]{3}' || { echo err message >&2; exit 1; }

this could be another way
#!/bin/bash
#Stored input parameter 1 in a variable
perm="$1"
#Checking if inserted parameter is empty, in that case the script will show a help
if [ -z "${perm}" ];then
echo "Usage: $0 <permission>"
echo "I.e.: $0 777"
exit
else
#if the parameter is not empy, check if each digit is between 0-7
check=`echo $perm| grep [0-7][0-7][0-7]`
#if the result of command is empty that means that the input parameter contains at least one digit that's differs from 0-7
if [ -z "${check}" ];then
echo "Error: each digit in the parameter must be between 0 and 7"
fi
fi
that's the output
[shell] ➤ ./test9.ksh 999
Error: each digit in the parameter must be between 0 and 7
[shell] ➤ ./test9.ksh 789
Error: each digit in the parameter must be between 0 and 7
[shell] ➤ ./test9.ksh 779
Error: each digit in the parameter must be between 0 and 7
[shell] ➤ ./test9.ksh 777

Related

Having difficulty writing a script to sort words

I am dealing with sorting words in Bash according to a given argument. I am given either argument -r, -a , -v or -h and according to it there are options to sort the words, as you can see at my "help".
Somehow, if I pass the argument -r it creates an error. I really don't understand what I am doing wrong, as if[["$arg"=="-a"]] works, but I have to use case somehow.
Here is my code:
#!/bin/bash
# Natalie Zubkova , zubkonat
# zubkonat#cvut.fel.cz , LS
#help
help="This script will calculate occurances of words in a given file, and it will sort them according to the given argument in following order> \n
without parametre = increasing order according to a number of occurance\n
-r = decreasing order according to a number of occurance\n
-a = in alphabetical increasing order\n
-a -r = in alphabetical decreasing order\n
There are also special cases of the given parametre, when the script is not sorting but:\n
-h = for obtaining help \n
-v = for obtaining a number of this task "
# this function will divide a given chain into a words, so we can start calculating the occurances, we also convert all the capital letters to the small ones by - tr
a=0;
r=0;
EXT=0;
if [ "$1" == "-h" ]; then
echo $help
exit 0
fi
if [ "$2" == "-h" ]; then
echo $help
exit 0
fi
if [ "$1" == "-v" ]; then
echo "5"
exit 0
fi
if [ "$2" == "-v" ]; then
echo "5"
exit 0
fi
function swap {
while read x y; do
echo "$y" "$x";
done
}
function clearAll {
sed -e 's/[^a-z]/\n/gI' | tr '[A-Z]' '[a-z]' | sort | uniq -c |awk '{i++; if(i!=1) print $2" "$1}' #swap
}
for arg do
case "$arg" in
"-a")
a=1
;;
"-r")
r=1
;;
"-v")
echo "5" #number of task is 5
exit 0
;;
"-h")
echo $help
exit 0
;;
"-?")
echo "invalid parametre, please display a help using argument h"
exit 0
;;
esac
done
#Sort according to parametres -a and -r
function sortWords {
if [[ a -eq 1 ]]; then
if [[ r -eq 0 ]]; then
clearAll | sort -nk1
fi
fi
if [[ a -eq 1 ]]; then
if [[ r -eq 1 ]]; then
clearAll | sort -nk1 -r
fi
fi
if [[ r -eq 1 ]]; then
if [[ a -eq 0 ]]; then
clearAll | sort -nk2 -r
fi
fi
if [[ a -eq 0 ]]; then
if [[ r -eq 0 ]]; then
clearAll | sort -nk2
fi
fi
}
#code is from Stackoverflow.com
function cat-all {
while IFS= read -r file
do
if [[ ! -z "$file" ]]; then
cat "$file"
fi
done
}
#histogram
hist=""
for arg do
if [[ ! -e "$arg" ]]; then
EXT=1;
echo "A FILE DOESNT EXIST" >&2
continue;
elif [[ ! -f "$arg" ]]; then
EXT=1;
echo "A FILE DOESNT EXIST" >&2
continue;
elif [[ ! -r "$arg" ]]; then
EXT=1;
echo "A FILE DOESNT EXIST" >&2
continue;
fi
done
for arg do
hist="$hist""$arg""\n"
done
echo -e "$hist" | cat-all | sortWords
exit $EXT;
Here is what our upload system which does some test to see if our program works says:
Test #6
> b5.sh -r ./easy.txt
ERROR: script output is wrong:
--- expected output
+++ script stdout
## --- line 1 (167 lines) ; +++ no lines ##
-the 89
-steam 46
-a 39
-of 37
-to 35
...
script written 484 lines, while 484 lines are expected
script error output:
A FILE DOESNT EXIST
cat: invalid option -- 'r'
Try `cat --help' for more information.
script exit value: 1
ERROR: Interrupted due to failed test
If anyone could help me I would really appreciate it.
You forgot to move the parameter index position with shift:
"-r")
r=1
shift
;;
shift above moves to the next command line arg: ./easy.txt in your case.
Without it, read -r file will read -r instead of the file name.

why does not it enter into arg1 if condion, though arg1 is commandline argument

if [ "$#" -ne 1 ]; then
flag=1;
elif ! [[ "$1" == "arg1" || "$1" == "arg2" || "$1" == "arg3" || ...... ]]; then
echo "Invalid"
flag=1;
fi
if [ "$flag" == "1" ]; then
echo "Usage of script...."
exit
fi
count="$(ls *.mov | wc -l)"
if [[ "$count" -eq 0 ]]
then
echo there are 0 .mov files in this path
elif [[ "$count" -eq 1 ]]
then
echo there is 1 .mov file in this path
vlc *.mov
elif [[ $1 = "arg1" ]] ; then
echo entered the tough part....coz its not entering`enter code here`
elif [[ "$1" == "arg2" ]] || [[ "$1" == "arg10" ]] ; then
echo entered here atleast...but not entering
else
script continues
The code does not enter elif conditions involving command line arguments. Tried =, ==, -eq, double square braces, single square braces. But it does not enter, pls help
you should add a disclaimer at the head of the script: " #!/bin/bash"
I tried your script and it does get into the elif.
the code I used is:
if [ "$#" -ne 1 ]; then
echo "not 1 arg"
flag=1;
elif ! [[ "$1" == "arg1" || "$1" == "arg2" || "$1" == "arg3" ]]; then
echo "Invalid"
flag=1;
else
echo "else"
fi
and the input/output are:
$ . script.sh 1 2
not 1 arg
$ . script.sh 1
Invalid
$ . script.sh arg1
else
I tried the second part and it is also working:
count=$2
if [[ "$count" -eq 0 ]] ;then
echo "there are 0 .mov files in this path"
elif [[ "$count" -eq 1 ]] ;then
echo "there is 1 .mov file in this path"
vlc *.mov
elif [[ $1 = "arg1" ]] ; then
echo "arg1 "
elif [[ "$1" == "arg2" ]] || [[ "$1" == "arg10" ]] ; then
echo "arg2 or arg10 "
else
echo "else"
fi
and tested it (second argument is "count"):
$ . script.sh arg1 0
there are 0 .mov files in this path
$ . script.sh 1 0
there are 0 .mov files in this path
$ . script.sh arg10 0
there are 0 .mov files in this path
$ . script.sh arg1 1
there is 1 .mov file in this path
The program 'vlc' is currently not installed. To run 'vlc' please ask your administrator to install the package 'vlc-nox'
$ . script.sh arg10 1
there is 1 .mov file in this path
The program 'vlc' is currently not installed. To run 'vlc' please ask your administrator to install the package 'vlc-nox'
$ . script.sh 1 1
there is 1 .mov file in this path
The program 'vlc' is currently not installed. To run 'vlc' please ask your administrator to install the package 'vlc-nox'
$ . script.sh arg1 2
arg1
$ . script.sh 1 2
else
$ . script.sh arg10 2
arg2 or arg10
You should look into the bash case statement http://mywiki.wooledge.org/BashGuide/TestsAndConditionals#Choices_.28case_and_select.29
For this particular script, it will make your script easier to read and your branching problem will most likely go away..
if your purpose is to handle the arguments passed to the script by command line it's better to use the getopts bash
this is just an example that you can adapt to your scope:
#!/bin/bash
function usage {
echo "usage: ..."
}
while getopts f:o:h opt; do
case $opt in
f)
fileName=$OPTARG
echo "filename[$fileName]"
;;
o)
otherargs=$OPTARG
echo "otherargs[$otherargs]"
;;
h)
usage && exit 0
;;
?)
usage && exit 2
;;
esac
done
~
output
[myShell] ➤ ./n -h
usage: ...
[myShell] ➤ ./n -f myfilename
filename[myfilename]
[myShell] ➤ ./n -o other
otherargs[other]
[myShell] ➤ ./n -l
./n: illegal option -- l
usage: ...

How to check length of an argument in bash script

how can I check the length of an argument in bash script?
Let's say that the length of an argument should not exceed 1.
args=("$#")
if [ ${args[0] -gt 1]; then
echo "Length of arg. 1 must be 1"
fi
This however doesn't work properly, since it will check if args[0] > 1 and not len(args[0] > 1):
./sth.sh 2 1 1
"Length of arg. 1 must be 1"
LENGTH is 1, but it still echoes.
I also tried this:
args=("$#")
if [ ${#args[0] -gt 1]; then
echo "Length of arg. 1 must be 1"
fi
However, it doesn't echo anything.
You can use this:
if [ "$#" -ne 1 ]; then
echo "Illegal number of parameters"
fi
Or
if test "$#" -ne 1; then
echo "Illegal number of parameters"
fi
Later check the length of each argument like this:
for var in "$#"
do
check=${#var}
if [ $check -ne 1 ]; then echo "error" ; exit
fi
done

Bash~ how can I make so if argument 1 contains a negative int or a string it exits

Here is my script, im having trouble in elif statement. I need it to exit if user enters a non negative integer as argument 1 or a string..
#!/bin/sh
n="0"
m="$1"
if test $# != "2"
then
echo "Usage: ./echon.sh <number of lines> <string>"
exit 1
elif [ $1 -eq "[^0-9]" ] || [ $1 = "[a-zA-Z]" ]
then
echo "./echon.sh: argument 1 must be a non-negative integer"
exit 1
else
while [ "$n" -lt "$m" ]
do
echo "$2"
n=$(($n + 1))
done
fi
A quick rewrite
#!/bin/bash
shopt -s extglob
if (( $# != 2 )); then
echo "Usage: $0 <number of lines> <string>"
elif [[ $1 != 0 && $1 != [1-9]*([0-9]) ]]; then
echo "$0: argument 1 must be a non-negative integer"
else
n=0
while (( n < $1 )); do
echo "$2"
((n++))
done
fi
Notes
using [[ ... ]] for string comparisons
using (( ... )) for arithmetic expressions
using extended globbing to match a non-negative integer (enforcing a non-zero number does not begin with 0, to avoid potential invalid octal numbers)
Replace your elif line with the following:
elif echo $1 | grep -qv "^[0-9][0-9]*"

Is there an easy way to determine if user input is an integer in bash?

I am a new student to bash scripting, and I am stumped on an assignment question.
I was wondering if there is an easy way to determine whether a users' input is an integer or not. More specifically, if a user is prompted to input an integer, is there a quick check to validate?
One way is to check whether it contains non-number characters. You replace all digit characters with nothing and check for length -- if there's length there's non-digit characters.
if [[ -n ${input//[0-9]/} ]]; then
echo "Contains letters!"
fi
Another approach is to check whether the variable, evaluated in arithmetic context, is equal to itself. This is bash-specific
if [[ $((foo)) != $foo ]]; then
echo "Not just a number!"
fi
This is kind of a kludge, it's using -eq for something other then what it was intended, but it checks for an integer, if it doesn't find an int it returns both an error which you can toss to /dev/null and a value of false.
read input
if [[ $input ]] && [ $input -eq $input 2>/dev/null ]
then
echo "$input is an integer"
else
echo "$input is not an integer or not defined"
fi
You can test by using Regular expression
if ! [[ "$yournumber" =~ ^[0-9]+$ ]] ;
then exec >&2; echo "error: Not a number"; exit 1
fi
I found this post http://www.unix.com/shell-programming-scripting/21668-how-check-whether-string-number-not.html that talks about this.
If your input does not need to check if there is a +/- on the number, then you can do:
expr $num + 1 2> /dev/null
if [ $? = 0 ]
then
echo "Val was numeric"
else
echo "Val was non-numeric"
fi
Here is another way of doing it. It's probably a bit more elaborate than needed in most cases, but would handle decimals also. I had written the below code to get rounded number. It also checks for numeric input in the process.
#--- getRound -- Gives number rounded to nearest integer -----------------------
# usage: getRound <inputNumber>
#
# echos the rounded number
# Best to use it like:
# roundedNumber=`getRound $Number`
# check the return value ($?) and then process further
#
# Return Value:
# 2 - if <inputNumber> is not passed, or if more arguments are passed
# 3 - if <inputNumber> is not a positive number
# 0 - if <inputNumber> is successfully rounded
#
# Limitation: Cannot be used for negative numbers
#-------------------------------------------------------------------------------
getRound (){
if [ $# -ne 1 ]
then
exit 2
fi
#--- Check if input is a number
Input=$1
AB=`echo A${Input}B | tr -d [:digit:] | tr -d '.'`
if [ "${AB}" != "AB" ] #--- Allow only '.' and digit
then
exit 3
fi
DOTorNone=`echo ${Input} | tr -d [:digit:]` #--- Allow only one '.'
if [ "${DOTorNone}" != "" ] && [ "${DOTorNone}" != "." ]
then
exit 3
fi
echo $Input | awk '{print int($1+0.5)}' #--- Round to nearest integer
}
MyNumber=`getRound $1`
if [ $? -ne 0 ]
then
echo "Empty or invalid input passed"
else
echo "Rounded input: $MyNumber"
fi
This one works for me, handling empty input case.
if [ $input -eq $input 2>/dev/null -o $input -eq 0 2>/dev/null ]
then
echo Integer
else
echo Not an integer
fi

Resources