Why is my If Statement in Bash not working? - bash

Hi I'm creating an archiving system in bash with a long and messy if statement which doesn't currently work with the current errors being on the last few lines with the else if statement. Although I expect there are further errors with this statement anyway. The variable choice is from a menu which displays in the terminal. So if they select option 1 the user then has to enter data to be written to the crontab file.
if [ $choice -eq "1" ] then
echo "Enter the MINUTE"
read minute
if [ $minute -eq 0 ] then
GLOBIGNORE=*
minute="*"
echo minute
fi
echo "Enter the Hour"
read hour
if [ $hour -eq 0 ] then
GLOBIGNORE=*
hour="*"
echo hour
fi
echo "Enter the Day"
read day
if [ $day -eq 0 ] then
GLOBIGNORE=*
day="*"
echo day
fi
echo "Enter the Month"
read month
if [ $month -eq 0 ] then
GLOBIGNORE=*
month="*"
echo month
fi
echo "Enter the weekday"
read weekday
if [ $weekday -eq 0 ] then
GLOBIGNORE=*
weekday="*"
echo weekday
fi
echo $minute $hour $day $month $weekday " date > ~/testcron.log" > testcron.txt fi
elif [ $choice -eq "2" ]
then
echo "Enter the Source and Destination Locations"
fi

There are several issues with your code:
if [ $hour -eq 0 ] then
GLOBIGNORE=*
hour="*"
echo hour
fi
In general (all test []) are missing a ; after it:
if [ $hour -eq 0 ]; then
The echo hour will not print the value of var hour but the word hour. Change to echo "$hour" (yes, quoted). Also, there is no need to set the variable GLOBIGNORE to * if vars are properly quoted.
The vars here are not quoted, that is a reason for it to fail (or to need GLOBIGNORE):
echo $minute $hour $day $month $weekday
Change to:
echo "$minute $hour $day $month $weekday"
The redirection on that same line is a plain >, that will empty the file.
If you want to append to the files, do as this:
echo "$minute $hour $day $month $weekday" "$(date >> ~/testcron.log)" >>testcron.txt
In that line there is an unneeded additional fi
This script may be of help:
get(){
read -p "$1" "$2"
if [ "$((${!2}))" -eq 0 ]; then
eval "$2"="*"
echo "${!2}"
fi
}
read -p "Choice?:" choice
if [ "$choice" -eq "1" ]; then
get "Enter the MINUTE" minute
get "Enter the Hour" hour
get "Enter the Day" day
get "Enter the Month" month
get "Enter the weekday" weekday
date >> ~/testcron.log
echo "$minute $hour $day $month $weekday" >> testcron.txt
elif [ "$choice" -eq "2" ]; then
echo "Enter the Source and Destination Locations"
fi

You are missing a semi-colon:
if [ $choice -eq "1" ]; then
or
if [ $choice -eq "1" ]
then
A semi-colon or a newline is required because the command is actually [ and has to be terminated after the ], which is just the last argument given to [.
That is the old test (or [) syntax, you could also use:
if (( choice == 1 ))
then

Related

Age calculation program with completed months and days

Good afternoon I have a program in bash to calculate the age by entering the data of the year, month and day of birth. But I would also like to calculate the completed months and days. What would be the conditions that I should add to my code. Please help
echo "Enter your year of birth"
read a_nac
echo "Enter your month of birth"
read m_nac
echo "Enter your day of birth"
read d_nac
echo "-----------Birth Date---------"
echo $d_nac $m_nac $a_nac
a_act=$(date +%Y)
m_act=$(date +%m)
d_act=$(date +%d)
echo "-----------Current Date-------------"
echo $d_act $m_act $a_act
let edad=$a_act-$a_nac
if [ $m_act -lt $m_nac ]; then
((edad--))
elif [ $m_nac -eq $m_act -a $d_act -lt $d_nac ]; then
((edad--))
fi
echo "-----------Age-------------------"
echo "You have" $edad "years"
It's a bit complex to find a generic solution. For the dates after the epoch we can convert both the dates with date +%s and make a plain subtraction.
A more generic solution follows:
echo "Enter your year of birth"
read a_nac
echo "Enter your month of birth"
read m_nac
echo "Enter your day of birth"
read d_nac
echo "-----------Birth Date---------"
echo $d_nac $m_nac $a_nac
a_act=$(date +%Y)
m_act=$(date +%-m)
d_act=$(date +%-d)
echo "-----------Current Date-------------"
echo $d_act $m_act $a_act
let years=$a_act-$a_nac
if [ $m_act -lt $m_nac ]; then
((years--))
let months=$m_nac-$m_act
elif [ $m_act -ge $m_nac ]; then
let months=$m_act-$m_nac
elif [ $m_nac -eq $m_act -a $d_act -lt $d_nac ]; then
((years--))
fi
if [ $d_act -lt $d_nac ]; then
((months--))
let days=30-$d_nac+$d_act
else
let days=$d_act-$d_nac
fi
echo "-----------Age-------------------"
echo "You have $years years, $months months, $days days"
The line
let days=30-$d_nac+$d_act
does not take into account that not all the months have 30 days and the case of leap months. The correction is left to the reader ;)

How to call another script within a script with bash

Hello here is my primary script. The test2.sh is just an echo "it worked"
what happens when I try and call from the original loop, it gets to the correct file then echo's infinite "it worked" where it should just be doing it once.
Any idea why? I really want to have another loop called outside of the main script that won't interfere, but still learning bash =P
#!/bin/bash
number=1
while true
do
if [ "$number" -eq "1" ]; then
echo "hello 1!"
elif [ "$number" -eq "2" ]; then
echo "hello 2!"
elif [ "$number" -eq "3" ]; then
echo "hello 3!"
elif [ "$number" -eq "4" ]; then
./test2.sh & continue
fi
sleep 5
((number++))
echo $number
done
first observation & is not a logical operator, & runs the precedding command in the background. Use && for logical operations.
what you need is a break keyword not a continue keyword . If you use the break keyword, the loop will stop executing. The continue keyword only rexecutes the loop , and since number is 4 , this branch of code will always run elif [ "$number" -eq "4" ]; then
working code
#!/bin/bash
number=1
while true
do
if [ "$number" -eq "1" ]; then
echo "hello 1!"
elif [ "$number" -eq "2" ]; then
echo "hello 2!"
elif [ "$number" -eq "3" ]; then
echo "hello 3!"
elif [ "$number" -eq "4" ]; then
./test2.sh && break
fi
sleep 5
((number++))
echo $number
done
or you can do this
for number in {1..4};do
(( number == 4 )) && ./test2.sh || echo "$number"
sleep 5
done

Multiple variables in a CASE statement-BASH

st file
failed" "aa" "2018-04-03T17:43:38Z" "2018-04-03T18:43:38Z"
I have code which reads line into varaible and compares it with differenr values ("succeded","failed","aborted") and writes appropriate output.
while read -r status name startdate enddate; do
case "$status" in
"\"aborted\"")
echo "Job " $name "aborted"
;;
"\"failed\"")
echo "Job " $name "failed" " In project Demo"
;;
"\"succeeded\"")
echo "Job " $name "success"
;;
#*) echo 0 + $name
esac
exit 0
done<st.txt
Now want to add another condition in existing case statement: compare two dates and if difference between them is greather than 5 minutes and status "aborted" print
"aborted-long running", if time difference is less than 5 minutes and status "aborted" then just print "aborted" for other conditions no need to change anything
i imported another variable elapsed which will calculate difference between start and end date
is it possible to put this variable (together with $status in case statement)
i introduced elapsed variable in code but don't know how to integrate with existing case
while read -r status name startdate enddate; do
startdate=${startdate//\"/}
stime=$(date -d "${startdate/T/ }" +%s)
enddate=${enddate//\"/}
etime=$(date -d "${enddate/T/ }" +%s)
let elapsed=etime-stime
case "$status" in
"\"aborted\"")
echo "Job " $name "aborted"
;;
"\"failed\"")
echo "Job " $name "failed"
;;
"\"succeeded\"")
echo "Job " $name "success"
;;
*) echo 0 + $name
esac
exit 0
done<st.txt
Just add some more code to the aborted case branch:
case "$status" in
'"aborted"')
[[ $elapsed -gt 300 ]] && extra="-long running" || extra=""
echo "Job $name aborted $extra"
;;
'"failed"')
echo "Job $name failed"
;;
'"succeeded"')
echo "Job $name success"
;;
*) echo "0 + $name" ;;
esac
I would encourage you to use indentation on your code.
Also, quote your variables
Multiple IF statements: i thought it's more complicated
if [ "$status" == "\"aborted\"" ] && [ "$elapsed" -gt 300 ]; then echo "Long Running Process-Demo"
elif [ "$status" == "\"aborted\"" ] && [ "$elapsed" -lt 300 ]; then echo "Aborted-Demo"
elif [ "$status" == "\"failed\"" ]; then echo "Job" $name "failed-Demo"
elif [ "$status" == "\"succeeded\"" ]; then echo "Job" $name "Succeded"
fi

Illegal number when decimal point is used in bash script

I am very new to bash scripting and I have a problem with a script.
#!/bin/sh
timestamp() {
date +"%Y-%m-%d %T"
}
LOGDIR="/home/pi/tempcontroller_rum1.log"
VALUE=28
TEMP=$(cat /home/pi/temperaturloggar/rum1.txt)
STATUS=`cat /sys/class/gpio/gpio18/value`
echo `timestamp` " Info: Temperature: $TEMP" >>$LOGDIR
if [ $TEMP -le $VALUE ] && [ $STATUS -eq 0 ]
then
echo `timestamp` "Too Cold, Heater started." >>$LOGDIR
echo "1">/sys/class/gpio/gpio18/value
print $TEMP
elif [ $TEMP -ge $VALUE ] && [ $STATUS -eq 1 ]
then
echo `timestamp` "Warm enough, Heater stoped." >>$LOGDIR
echo "0">/sys/class/gpio/gpio18/value
print $TEMP
fi
The file "rum1" contains a number that hs several decimals I think this is the problem, becouse when I runt the script I get
./tempcontroller_rum1.sh: 12: [: Illegal number: 25.10000038147
./tempcontroller_rum1.sh: 17: [: Illegal number: 25.10000038147
Any advice? I need the script to read from the .txt, compare it to the VALUE and then turn on/of the GPIO depending on if its lower or higher then the VALUE
If I manualy set the rum1.txt to 24. The script works, but I get the folowing warnings/errors.
Warning: unknown mime-type for "24" -- using "application/octet-stream"
Error: no such file "24"
How can I solve this?
My Lua script writing to the rum.txt can I round this up/dwn
commandArray = {}
if (devicechanged['Rum1']) then
local file = io.open("/home/pi/temperaturloggar/rum1.txt", "w")
file:write(tonumber(otherdevices_temperature['Rum1']))
file:close()
end
return commandArray
You can use bc to do the floating point comparison:
$ VALUE=28
$ TEMP=25.10000038147
$ bc<<<"$TEMP < $VALUE"
1
In you case :
if [ $(bc<<<"$TEMP < $VALUE") -eq 1 ] && [ $STATUS -eq 0 ]
To answer the question in the comment, use math.floor to round down, as in:
file:write(math.floor(otherdevices_temperature['Rum1']))
To round up, use
file:write(math.floor(otherdevices_temperature['Rum1']+0.5))
Now my script is working as it shuld and I wanted to post the code if anyone els is having the same question as me.
#!/bin/bash
timestamp() {
date +"%Y-%m-%d %T"
}
LOGDIR="/home/pi/tempcontroller_rum1.log"
VALUE=23
TEMP=$(cat /home/pi/temperaturloggar/rum1.txt)
STATUS=`cat /sys/class/gpio/gpio18/value`
echo `timestamp` " Info: Temperature: $TEMP" >>$LOGDIR
if [ $(bc<<<"$TEMP < $VALUE") -eq 1 ] && [ $STATUS -eq 0 ]
then
echo `timestamp` "Too Cold, Heater started." >>$LOGDIR
echo "1">/sys/class/gpio/gpio18/value
elif [ $(bc<<<"$TEMP < $VALUE") -eq 0 ] && [ $STATUS -eq 1 ]
then
echo `timestamp` "Warm enough, Heater stoped." >>$LOGDIR
echo "0">/sys/class/gpio/gpio18/value
fi

Expected result not return in shell script

I wrote the following code in shell script:
#!/bin/bash
tput clear
a=$(date +"%k")
if [ $a -lt 12 ]
then
echo "Hi!Good Morning"
fi
if [ $a -ge 12 -a $a -le 17 ]
then
echo "Hi!Good Afternoon"
fi
if [ $a -gt 17 -a $a -le 19 ]
then
echo "Hi!Good Evening"
fi
if [ $a -gt 19 -a $a -le 24 ]
then
echo "Hi!Good Night"
fi
while [ : ]
do
echo "BCSE!!\c"
read comm
set comm
case "$1" in
[""])
continue
;;
esac
case "$1" in
["editme"])
xdg-open "$2"&
;;
esac
case "$1" in
["newd"])
mkdir -p "$2"
;;
esac
case "$1" in
["mycontent"])
if [ -f "$2" ]
then
xdg-open "$2"&
else
echo "File doesn't exist"
fi
;;
esac
case "$1" in
["exitbcse"])
break
;;
esac
case "$1" in
[*])
echo "Wrong command!!";;
esac
done
The output should be :
Hi!Good morning
BCSE!!editme filename
now the file doesn't open instead I get
Hi!Good morning
BCSE!!editme filename
BCSE!!
Instead of:
while [ : ]
You may want to write:
while :
or
while true
while [ : ] may work, but not for the right cause, that sentence runs the command [, the command [ checks the expression you wrote inside, as it is a non-empty string it returns a true value (a zero), to ilustrate this, if you run while [ false ] you will also get an infinite loop.
And in the case control structures the options must be written without [] and "".
case "$1" in
exitbcse)
break
;;
esac
Edit:
Check this example with the corrections I described above and also other fixes:
#!/bin/bash
tput clear
a=$(date +"%k")
if [ $a -lt 12 ]
then
echo "Hi!Good Morning"
elif [ $a -ge 12 -a $a -le 17 ]
then
echo "Hi!Good Afternoon"
elif [ $a -gt 17 -a $a -le 19 ]
then
echo "Hi!Good Evening"
elif [ $a -gt 19 -a $a -le 24 ]
then
echo "Hi!Good Night"
fi
while true
do
echo "BCSE!!\c"
read comm option
case "$comm" in
"")
continue
;;
"editme")
xdg-open "$option"&
;;
"newd")
mkdir -p "$option"
;;
"mycontent")
if [ -f "$option" ]
then
xdg-open "$option"&
else
echo "File doesn't exist"
fi
;;
"exitbcse")
break
;;
*)
echo "Wrong command!!";;
esac
done

Resources