Addition in bash

Ray Parrish crp at cmc.net
Wed Oct 14 17:48:29 UTC 2009


David N. Lombard wrote:
> Ray Parrish wrote:
>   
>> Ray Parrish wrote:
>>     
>>>
>>>
>>> #!/usr/bin/env bash
>>>       
>
> #!/bin/bash
>
> env is used when you don't know the absolute path of the binary.  bash 
> is /bin/bash--to move it elsewhere would cause intense carnage.
>
>   
>>> # Usage: Timer.sh n n
>>> # where n and n are numeric values expressed in seconds. The first n is 
>>> the interval of how often you would like to see updates to the timer 
>>> display.
>>> # The second n is the duration you would like th''''''''''''''''''e 
>>> timer to run before shutting off.
>>> # To stop the script at any point execute a CTRL-Z in Terminal. By doing 
>>> this you can use the Timer script as a stop watch, just set a long
>>> # enough duration to cover the event length you are attempting to time, 
>>> and hit CTRL-Z to stop timing when the event is over.
>>>       
>
> You want <Ctrl-C>.  <Ctrl-Z> "stops" (read suspends) the job; you would 
> then typically type "bg" to let the job resume executing in the 
> background (as if you have suffixed the original command with a "&") or 
> type "fg" to bring it back to the foreground.  If you've been using 
> <Ctrl-Z>, you probably have a few things suspended.  Type "jobs" and see 
> what it shows.
>   
Thanks for the tip. I did indeed have about twenty Timer.sh jobs 
suspended when I looked. I have since changed the script to check for a 
key press each time through the loop, and exit if any character key has 
been pressed.
>   
>>> Minutes=0;
>>>       
>
> The semicolon is extraneous.  Don't program bash in C.
>   
That's the second time today I've learned that. I've stripped all of the 
semi-colons from my code.
>   
>>> Seconds=0;
>>> Elapsed=0;
>>> Duration=$2;
>>> Interval=$1;
>>> # if Interval is blank (unspecified)
>>> if [ "$Interval" == "" ]
>>>     then
>>>             Interval=1; # set default interval of one second is set
>>> fi
>>>       
>
> Interval=${1:-1}
>   
Could you please explain the above line, and the one below for Duration, 
as I do not see what that code is supposed to be doing.
>   
>>> # if Duration is blank (unspecified)
>>> if [ "$Duration" == "" ]
>>>     then
>>>            Duration=300; # set default interval of 300 seconds.
>>> fi
>>>       
>
> Duration=${2:-300}
>
>   
>>> echo "$Interval Interval"; # echo interval setting
>>> echo "$Duration Duration": # echo Duration setting
>>> # While elapsed time is less than the Duration setting do loop
>>> while [ $Elapsed -lt $Duration ]
>>> # first sleep for the interval
>>>   sleep "$Interval";
>>> # Increment Seconds and Elapsed by the Interval setting
>>>   Seconds=$(( $Seconds +$Interval ));
>>>   Elapsed=$(( $Elapsed +$Interval ));
>>>       
>
> (( Seconds += Interval ))
> (( Elapsed += Interval ))
>   
Thanks for the incrementation tip. I'll change the script to use your 
method now.
>   
>>> # if Seconds equals 60
>>>   if [ $Seconds == 60 ]
>>>       then
>>>               Seconds=0; # reset Seconds to zero
>>>               Minutes=$(( $Minutes + 1)); # add one to the Minutes value
>>>   fi
>>> # clear the screen between each timer update
>>>   clear
>>> # Update the timer display to the current value
>>>   echo "Elapsed Time: $Minutes Minutes $Seconds Seconds"
>>> done
>>> exit
>>>
>>> I do not know why padsp espeak would not work from within terminal, as 
>>> it works just fine in scripts I write within Kalarm.
>>>
>>> Later, Ray Parrish
>>>   
>>>       
>> OOPS! Here is a small correction that allows it to work correctly when 
>> the interval doesn't divide evenly into 60 seconds.
>>
>> # if Seconds equals 60 or is greater than 60 seconds
>>   if [ $Seconds == 60 ] || [ $Seconds -gt 60 ]
>>       then
>>               Seconds=$(( $Seconds - 60)); # trim 60 seconds off the 
>> reading and
>>               Minutes=$(( $Minutes + 1)); # add one to the Minutes value
>>   fi
>>     
>
>    if [[ $Seconds -ge 60 ]] ; then
>
> or
>
>    [[ $Seconds -ge 60 ]] && (( Seconds -= 60 )) && (( Minutes += 1 ))
>   
That last line did not work correctly, it decremented Seconds, but 
neglected to change the value of Minutes... got any idea why??? This 
error was with Interval set to 1 second, with Interval set to 7 seconds 
Minutes increments correctly.

Thanks again for all of the tips, I have made many changes to the script 
according to your tips, and here is the current version of the script 
which works quite well.

#!/usr/bin/env bash
# Usage: /folderpath/Timer.sh n n
# Where n and n are numeric values expressed in seconds. The first n is 
the interval in seconds of how often you would like to see updates to the
# timer display.
#
# The second n is the duration in seconds you would like the timer to 
run before shutting off. This is for use as an event timer.
#
# Replace folderpath with the actual path of folder names leading to the 
scripts location.
#
# To stop the script at any point press a character key in Terminal. By 
doing this you can use the Timer script as a stop watch, just set a long
# enough duration to cover at least the event length you are attempting 
to time, and hit any letter, number, or punctuation key to stop timing
# when the event is over. Adjust the Interval to the granularity of 
accuracy you need from the stop watch mode of operation.
#
# initialize variables
# elapsed Minutes
declare -i Minutes=0
# elapsed Seconds
declare -i Seconds=0
# Elapsed keeps track of how long the timer has been running.
declare -i Elapsed=0
# Duration is how long you want the timer to run in seconds.
Duration=$2
# Number of seconds left before timer ends.
Remainder=$Duration
# number of seconds between timer display updates.
Interval=$1
# if Interval is blank (unspecified)
if [ "$Interval" == "" ]
    then
            Interval=1 # set default interval of one second
fi
# clear the screen to begin displaying timer output.
clear
# display timer output
echo "Elapsed Time: $Minutes Minutes $Seconds Seconds"
echo "$Interval Second Interval" # echo interval setting
# read timeout for any key of one second forces us to trim 1 second from 
the Interval for proper execution.
(( Interval -=1 ))
# if Duration is blank (unspecified)
if [[ "$Duration" == "" ]]
    then
           Duration=300 # set default interval of 300 seconds.
fi
# finish first timer display screen
echo "$Duration Duration" # echo Duration setting
echo "$Remainder Seconds Remaining"
echo "To exit timer press any letter, number, or punctuation key."
echo "Timer will then exit after the next interval expires."
# While elapsed time is less than the Duration setting do loop till done.
while [[ $Elapsed -lt $Duration ]]
  do
# take care of overrun condition when Duration is not evenly divisible 
by Interval, resulting in leftover seconds,
if [[ "$Remainder" -lt "$Interval" ]]
    then
            # sleep only the number of seconds left to satisy Duration.
            sleep $Remainder
            # update Seconds to proper value
            Seconds=$(( $Seconds +$Remainder ))
            # clear the screen for last timer display
            clear
            # put up last timer display
            echo "Elapsed Time: $Minutes Minute $Seconds Seconds"
            echo "$(( $Interval +1 )) Second Interval" # echo interval 
setting
            echo "$Duration Seconds Duration" # echo Duration setting
            echo "0 Seconds Remaining"
            echo "Timer has expired."
            # we're done, so exit the script.
            exit
fi
# sleep for the interval specified if interval is 1 or greater
if [[ $Interval -ne 0 ]]
   then
           sleep "$Interval"
fi
# Increment Seconds and Elapsed by the Interval setting + the 1 second 
read timeout value.
  (( Seconds += Interval + 1 ))
  (( Elapsed += Interval + 1 ))
# if Seconds equals 60 or is greater than 60 seconds, trim 60 from 
Seconds value, and add one to Minutes value.
if [[ $Seconds -ge 60 ]]
 then
              Seconds=$(( $Seconds - 60)); # trim 60 seconds off the 
reading and
              Minutes=$(( $Minutes + 1)); # add one to the Minutes value
  fi
# check to see how much time is left to run
Remainder=$(( $Duration -$Elapsed ))
# clear the screen between each timer update
clear
# Update the timer display to the current values
if [ $Minutes == 1 ]
   then
           echo "Elapsed Time: $Minutes Minute $Seconds Seconds"
           echo "$(( $Interval +1 )) Second Interval" # echo interval 
setting
           echo "$Duration Seconds Duration" # echo Duration setting
           echo "$Remainder Seconds Remaining"
           if [[ $Remainder -ne 0 ]]
               then
                      echo "To exit timer press any letter, number, or 
punctuation key."
                      echo "Timer will then exit after the next interval 
expires."
               else
                      echo "Timer has expired."
           fi
   else
           echo "Elapsed Time: $Minutes Minutes $Seconds Seconds"
           echo "$(( $Interval +1 )) Second Interval" # echo interval 
setting
           echo "$Duration Seconds Duration" # echo Duration setting
           echo "$Remainder Seconds Remaining"
           if [[ $Remainder -ne 0 ]]
               then
                      echo "To exit timer press any letter, number, or 
punctuation key."
                      echo "Timer will then exit after the next interval 
expires."
               else
                      echo "Timer has expired."
           fi
fi
# check to see if the user wants to exit the script by polling for a key 
press.
read -t 1 -n 1 ExitFlag
# if a key was pressed, exit the script.
if [ "$ExitFlag" != "" ]
    then
            exit
fi
done
exit

Later, Ray Parrish

-- 
The Future of Technology.
http://www.rayslinks.com/The%20Future%20of%20Technology.html
Ray's Links, a variety of links to usefull things, and articles by Ray.
http://www.rayslinks.com
Writings of "The" Schizophrenic, what it's like to be a schizo, and other
things, including my poetry.
http://www.writingsoftheschizophrenic.com






More information about the ubuntu-users mailing list