LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Linux - General (https://www.linuxquestions.org/questions/linux-general-1/)
-   -   Shell Scripting Questions, Writing alarm clock script (https://www.linuxquestions.org/questions/linux-general-1/shell-scripting-questions-writing-alarm-clock-script-846941/)

burgsprinta 11-27-2010 04:54 PM

Shell Scripting Questions, Writing alarm clock script
 
I left the linux world for a few years and now i am trying to re-learn my shell scripting basics. I am writing a script for an alarm clock, but i seem to be running into a few issues. My script is posted below. If anyone could help, that would be great. Thanks.

------------------------------------------------------------
#!/bin/bash
declare -i H
declare -i M
declare -i currentH
declare -i currentM
declare -i minutesLeft
declare -i hoursLeft
echo -e "What Hour (24 Format) do you want to Wake Up?"
read H
echo -e "What Minute?"
read M
echo `expr $H + 0`
currentH=`date +%H`
currentM=`date +%M`
echo "You Selected "
echo "$H:$M"
echo -e "\nIt is Currently $currentH:$currentM"

if [ "$currentH" < "echo $H" ];
then
hoursLeft= `expr $H - $currentH`
echo "$H - $currentH means You Have: $hoursLeft hours still"
fi

if [ "$currentH" > "$H" ]; then
hoursLeft= `expr $currentH - $H`
echo -e "\n$currentH - $H means you have $hoursLeft hours left \n"
fi

if [ "$currentH" == "$H" ]; then
hoursLeft= 0
echo -e "Taking a nap?\n"
fi

if [ "$currentM" < "$M" ];
then
minutesLeft= `expr $M - $currentM`
echo -e "$M -$currentM menas you have: $minutesLeft minutes still"
fi




----------------------------------

My script, instead of doing what it should, produces the following errors:

./alarm: line 19: echo 11: No such file or directory
./alarm: line 26: 6: command not found

17 - 11 means you have hours left

./alarm: line 37: -41: command not found
11 -52 menas you have: minutes still
expr: non-integer argument
52 - 11 means you have 0 minutes left

Sleeping... for hours and 0 minutes

sleep: invalid time interval `h'
Try `sleep --help' for more information
.

and if i choose the time 11:06, files called 11 and 6 are creating in the working directory. I am sure it is something really simple, but i haven't used linux or scripting on my computers in around 6 years. Thanks.

AlucardZero 11-27-2010 04:59 PM

Code:

if [ "$currentH" < "echo $H" ];
What are you trying to do here?

If you're comparing whether the current hour value is less than the alarm hour, then the "echo " makes no sense.

Could you repost your code at http://pastebin.com/ (select Bash) so we can have line numbers, monospacing, and syntax highlighting?

burgsprinta 11-27-2010 05:05 PM

Yes the echo does not make sense. Sorry about that. That actually should have been cleaned up, but I deleted it from my script, but forgot to delete it from here.

Thanks for the quick response.

GrapefruiTgirl 11-27-2010 05:07 PM

Here's a few tips to get you further along:

1) When comparing integers, do it like this:
Code:

if [ $H -gt 3 ]; then
Notice no quotations around the variable and the 3. When you use quotations, it should be for strings. -gt means "greater than", but there are other for less-than, equals, etc.. See bash man page for more on this.

2) When assigning values to vaiables, make sure there's no space after the "=" sign:
Code:

hoursLeft= `expr $H - $currentH`
          ^^


3) What does this do:
Code:

echo `expr $H + 0`
I mean, I know it supposed to echo something, but why? Just curious.... And for what it's worth, a bit less clunky way of doing simple math is like this, without expr:
Code:

echo $((VAR + 5))
echo $((VAR - OTHER_VAR))

Anyhow, check out that stuff and fix up your code a little. Then re-post the updated version for us in your next post. Please use code tags around your script ( see here: http://www.phpbb.com/community/faq.php?mode=bbcode#f2r1 )

Cheers.

burgsprinta 11-27-2010 05:09 PM

Quote:

Originally Posted by AlucardZero (Post 4173024)
Code:

if [ "$currentH" < "echo $H" ];
What are you trying to do here?

If you're comparing whether the current hour value is less than the alarm hour, then the "echo " makes no sense.

Could you repost your code at http://pastebin.com/ (select Bash) so we can have line numbers, monospacing, and syntax highlighting?


I am trying to set an alarm. I am going to add a command to invoke mplayer at the given time after the sleep commands, but this is more than anything just me trying to get back into scripting. Kind of frustrating, because I used to be able to do kind of task fairly easily. Somehow I completely forgot almost everything.

Posted to
http://pastebin.com/TMH7qtXk

Thanks

burgsprinta 11-27-2010 05:21 PM

Thanks AlucardZero and GrapefruiTgirl. Fixed it now. Runs well now. Here is the new code:

Code:

#!/bin/bash
declare -i H
declare -i M
declare -i currentH
declare -i currentM
declare -i minutesLeft
declare -i hoursLeft
echo -e "What Hour (24 Format) do you want to Wake Up?"
read H
echo -e "What Minute?"
read  M
currentH=`date +%H`
currentM=`date +%M`
echo "You Selected "
echo "$H:$M"
echo -e "\nIt is Currently $currentH:$currentM"

if [  $currentH -lt $H ];
        then
                hoursLeft=`expr $H - $currentH`
                echo "$H - $currentH means You Have: $hoursLeft hours still"
fi

if [ $currentH -gt $H ]; then
        hoursLeft=`expr $currentH - $H`
        echo -e  "\n$currentH - $H means you have $hoursLeft hours left \n"
fi

if [ $currentH == $H ]; then
        hoursLeft=0
        echo -e "Taking a nap?\n"
fi

if [ $currentM -lt $M ];
        then
                minutesLeft=`expr $M - $currentM`
                echo -e "$M -$currentM menas you have: $minutesLeft minutes still"
fi

if [ $currentM -gt $M ]; then

        minutesLeft=`expr $currentM - $M`
        echo -e "$currentM - $M means you have $minutesLeft minutes left \n"
fi

if [ $currentM == $M ]; then
        minutesLeft=0
        echo -e "and no minutes\n"
fi

echo -e "Sleeping... for $hoursLeft hours and $minutesLeft minutes \n"
sleep $hoursLeft\h
sleep $minutesLeft\m
mplayer ~/.alarm/alarm.mp3

Thanks everyone. Responses were quick and helpful.

burgsprinta 11-27-2010 05:24 PM

Is it necessary for me to declare the variables as integers?

GrapefruiTgirl 11-27-2010 05:33 PM

Quote:

Originally Posted by burgsprinta (Post 4173037)
Is it necessary for me to declare the variables as integers?

Not really, no. There must be a good reason that `declare` exists, (and actually I saw a recent example where it HAD to be used to define an array before using it) but I virtually never declare integers in any scripts I write. Doesn't seem to matter. The bash man page says:
Code:

A shell variable need not have its integer attribute turned on to be used in an expression.
So that's good for me. Someone else may have other thoughts on this...

GrapefruiTgirl 11-27-2010 05:39 PM

However! I should add that, something to keep in mind is that: if you're doing integer comparisons with variables, and one or another variable that has not been given a value (or zero), but you expect it to have an integer (not a string) then you can get errors. Like so:
Code:

root@reactor: [ $c -eq 3 ] && echo "equal"
bash: [: -eq: unary operator expected

I had not set the variable $c to anything at all, so the error results. If I had set an integer value to $c there would be no error. Using `declare` beforehand, does not prevent this.

burgsprinta 11-27-2010 06:00 PM

So i should set my integer variables equal to a non-zero number first? Thanks. The last code i posted doesn't work under all circumstances, but now that I have the very basics worked out, it shouldn't be too difficult. Thanks so much.

GrapefruiTgirl 11-27-2010 06:06 PM

Well, take for example the following simple script:
Code:

#!/bin/bash

NAME="bob"

if [ "$NAME" = "fred" ]; then
        c=5
fi

if [ $c -eq 5 ]; then
        echo "c equals five"
fi

Logically, there's nothing wrong with the script. However, you see there's the possibility that the $c variable will not get set to 5 (or any other integer) and so in this case, if you run the script, it will fail with an error (unless you set NAME="fred" in the beginning).

To prevent the error, make sure $c will ALWAYS contain some integer, including zero, before comparing it. Tthere should either be an ELSE case to go with the IF test of the name, which sets c to some value other than 5; or, you should initialise c=0 at beginning of the script. So:
Code:

#!/bin/bash

NAME="bob"

if [ "$NAME" = "fred" ]; then
        c=5
else
        c=1
fi

if [ $c -eq 5 ]; then
        echo "c equals five"
fi

Above, I added an ELSE, which sets $c to an integer; Now, $c ends up being an integer, regardless of what the $NAME was. No error is possible now, and we do not need to initialize c=0 in the start of the script.

burgsprinta 11-30-2010 01:37 AM

Finished Script.
 
Okay Thanks for all your help. After reading your replies I started over from scratch, and it works well now with no errors. Also, I added a countdown timer as well. Here is my new code. Try it out, and tell me what you think.

Code:

#!/bin/bash

#Script to set an alarm Clock, and use mplayer to wake up

#set alarm command

echo -e "Alarm Clock [a] or timer [t] (Case sensitive)?:"
read -N1 Choice

#if user Chose Alarm Clock
if [ $Choice == "a" ]; then
echo -e "\n"
setH=99
setM=99
currentH=99
currentM=99
hLeft=99
mLeft=99
echo -e "What Hour (24 Hour Format) Would you like to wake up?\n"
read setH
echo -e "What Minute?:  "
read setM

#get current time
currentH=`date +%H`
currentM=`date +%M`


echo -e "\nYou Selected $setH:$setM.\n"

echo -e "It is currently $currentH:$currentM.\n"



#correct for entries such as 1:01 01:03, anything where first digit
#is a 0.  There is probably an easier way, but I don't know it ;-)

#for setH
#--------------------------------------
if [ $setH == 00 ]; then
        setH=0
fi
if [ $setH == 01 ]; then
        setH=1
fi
if [ $setH == 02 ]; then
        setH=2
fi
if [ $setH == 03 ]; then
        setH=3
fi
if [ $setH == 04 ]; then
        setH=4
fi
if [ $setH == 05 ]; then
        setH=5
fi
if [ $setH == 06 ]; then
        setH=6
fi
if [ $setH == 07 ]; then
        setH=7
fi
if [ $setH == 08 ]; then
        setH=8
fi
if [ $setH == 09 ]; then
        setH=9
fi
#-----------------------------------------------

#for setM
#--------------------------------------
if [ $setM == 00 ]; then
        setM=60
        setH=$(($setH - 1))
fi
if [ $setM == 0 ]; then
        setM=60
        setH=$(($setH - 1))
fi
if [ $setM == 01 ]; then
        setM=1
fi
if [ $setM == 02 ]; then
        setM=2
fi
if [ $setM == 03 ]; then
        setM=3
fi
if [ $setM == 04 ]; then
        setM=4
fi
if [ $setM == 05 ]; then
        setM=5
fi
if [ $setM == 06 ]; then
        setM=6
fi
if [ $setM == 07 ]; then
        setM=7
fi
if [ $setM == 08 ]; then
        setM=8
fi
if [ $setM == 09 ]; then
        setM=9
fi
#-----------------------------------------------

#for CurrentH
#--------------------------------------
if [ $currentH == 00 ]; then
        currentH=0
fi
if [ $currentH == 01 ]; then
        currentH=1
fi
if [ $currentH == 02 ]; then
        currentH=2
fi
if [ $currentH == 03 ]; then
        currentH=3
fi
if [ $currentH == 04 ]; then
        currentH=4
fi
if [ $currentH == 05 ]; then
        currentH=5
fi
if [ $currentH == 06 ]; then
        currentH=6
fi
if [ $currentH == 07 ]; then
        currentH=7
fi
if [ $currentH == 08 ]; then
        currentH=8
fi
if [ $currentH == 09 ]; then
        currentH=9
fi
#-----------------------------------------------

#for currentM
#--------------------------------------
if [ $currentM == 00 ]; then
        currentM=0
fi
if [ $currentM == 01 ]; then
        currentM=1
fi
if [ $currentM == 02 ]; then
        currentM=2
fi
if [ $currentM == 03 ]; then
        currentM=3
fi
if [ $currentM == 04 ]; then
        currentM=4
fi
if [ $currentM == 05 ]; then
        currentM=5
fi
if [ $currentM == 06 ]; then
        currentM=6
fi
if [ $currentM == 07 ]; then
        currentM=7
fi
if [ $currentM == 08 ]; then
        currentM=8
fi
if [ $currentM == 09 ]; then
        currentM=9
fi
#-----------------------------------------------
#I realize that was pretty redundant.  Does anyone Know a better way?

#correct for a period of 24 hours
if [ $setH == $currentH ]; then
        if [ $setM -le $currentM ]; then
                setH=$(( $setH + 24))
                echo -e "Quite a long Nap You're Taking... About 1 Day\n"
        fi
fi

#If the Current Hour is less than the set hour
#subtract for hours remaining

if [ $currentH -lt $setH ]; then
        hLeft=$(($setH - $currentH))


#if current Hour is greater than set Hour
else if [ $setH -lt $currentH ]; then
        hLeftA=$(($currentH - $setH))
        hLeft=$((24 - $hLeftA))
       
#if equal
else
        hLeft=0
        echo -e "\nShort nap.  $hLeft hours"
fi
fi

#Make script output hours set; use correct plurality of "hour" or "hours"
if [ $hLeft == 1 ]; then
        echo "You have $hLeft hour"
        else if [ $hLeft -gt 1 ]; then
                echo "You have $hLeft hours"
        fi
fi
#Do the Same as Above, but for the Minutes
#subtract for minutes remaining

if [ $currentM -lt $setM ]; then
        mLeft=$(($setM - $currentM))


#if current Hour is greater than set Hour
else if [ $setM -lt $currentM ]; then
        mLeft=$(($currentM - $setM))

#if equal
else
        mLeft=0
        echo " and no minutes"
fi
fi
#make script output minutes set, with correct plurality of "minute or "minutes"
if [ $mLeft == 1 ]; then
        echo " and $mLeft Minute\n"
        else if [ $mLeft -gt 1 ]; then
                echo " and $mLeft Minutes"
        fi
fi
# Subtract 1 Hour if more than 0 minutes (since part of the hour is taken by the minutes)
if [ $mLeft -gt 0 ]; then
        hleft=$(($hleft -1))
fi
#invoke sleep
if [ $mLeft -gt 0 ]; then
echo -e "\nSleeping for: $hLeft hours and $mLeft minutes"
fi

if [ $mLeft == 0 ]; then
echo -e "\nSleeping for: $hLeft hours."
fi

sleep $hLeft\h
echo -e "\nNow 0 hours and $mLeft minutes\n"
sleep $mLeft\m
echo -e "DONE\n"

#run alarm Command
mplayer ~/alarm.mp3
exit 0
fi


#if user chose Timer
if [ $Choice == "t" ]; then
echo -e "\n"
H=99
M=99
echo -e "How many Hours:  "
read H

echo -e "\nHow many Minutes: "
read M
echo -e "You Chose $H hours and $M minutes."

echo -e "Setting Timer For $H:$M"
sleep $H\h
sleep $M\m
echo -e "\nDONE\n"

#run alarm command
mplayer ~/alarm.mp3
exit 0
fi



All times are GMT -5. The time now is 07:03 PM.