3

Let say, I need "command" to be run only if current time is from 11:10am till 2:30pm. How this can be done in bash script?

Something like below written in pseudo-language:

#!/bin/bash
while(1) {
    if ((currentTime > 11:10am) && (currentTime <2:30pm)) {
        run command;
        sleep 10;
    }
}

3 Answers3

7

The other answers overlook that when a number starts with 0, Bash will interprete it in radix 8. So, e.g., when it's 9am, date '+%H%M' will return 0900 which is an invalid number in Bash. (not anymore).

A proper and safe solution, using modern Bash:

while :; do
    current=$(date '+%H%M') || exit 1 # or whatever error handle
    (( current=(10#$current) )) # force bash to consider current in radix 10
    (( current > 1110 && current < 1430 )) && run command # || error_handle
    sleep 10
done

Could be shortened a bit if you accept a potential 10s delay for the first run:

while sleep 10; do
    current=$(date '+%H%M') || exit 1 # or whatever error handle
    (( current=(10#$current) )) # force bash to consider current in radix 10
    (( current > 1110 && current < 1430 )) && run command # || error_handle
done

Done!


Look:

$ current=0900
$ if [[ $current -gt 1000 ]]; then echo "does it work?"; fi
bash: [[: 0900: value too great for base (error token is "0900")
$ # oooops
$ (( current=(10#$current) ))
$ echo "$current"
900
$ # good :)

As xsc points out in a comment, it works with the ancient [ builtin... but that's a thing of the past :).

gniourf_gniourf
  • 44,650
  • 9
  • 93
  • 104
  • 1
    Works fine for me with single `[` and `]`, i.e. `[ $current -gt 1000 ]` does not throw an error. – xsc Nov 03 '13 at 17:28
  • Yes it's work well with external test command (and his fork `[`) but doesn't work with Bash internal instruction. I don't know why :/ `[ ~]$ test "09" -eq "9" && echo "ok"` result is `ok` and `[ ~]$ [[ 09 -eq 9 ]] && echo "ok"` result is `-bash: [[: 09: value too great for base (error token is "09")` – Idriss Neumann Nov 03 '13 at 17:30
  • 1
    @IdrissNeumann when you're using `test` and `[` in Bash, you're using the bash builtins, not the external commands. For the external commands you'd use `command test` and `command [` or use `enable -n test` and `enable -n [` before. – gniourf_gniourf Nov 03 '13 at 17:52
  • @gniourf_gniourf : Thank you for the clarification. I'd like to update my tutorials now ^^ (anyway for the story of protect its operands, it stay true in all cases). – Idriss Neumann Nov 03 '13 at 19:23
2

You could try something like :

currentTime=$(date "+%H%M")
if [ "$currentTime" -gt "1110" -a "$currentTime" -lt "1430" ]; then
    # ...
fi
# ...

Or :

currentTime=$(date "+%H%M")
if [ "$currentTime" -gt "1110" ] && [ $currentTime -lt "1430" ]; then
    # ...
fi
# ...

Or :

currentTime=$(date "+%H%M")
[ "$currentTime" -gt "1110" ] && [ "$currentTime" -lt "1430" ] && {
    # ...
}
# ... 

See man date for more details. You can also use a cron job to do more than run this script from 11:30.

NB : for your loop, you could use something like :

while [ 1 ]; do 
    #...
done

Or :

while (( 1 )); do 
    #...
done
Idriss Neumann
  • 3,760
  • 2
  • 23
  • 32
0

You can create a 4-digit number describing the current time with date +"%H%M". I think that could be used to compare against other times (in 24h-format) numerically:

while [ 1 ]; do
    currentTime=$(date +"%H%M");
    if [ "$currentTime" -gt 1110 ] && [ "$currentTime" -lt 1430 ]; then
        ...
    fi
    sleep 10;    # probably better to have this outside the if-statement
done

If you want to handle a timespan that includes midnight you just have to replace the && with ||.

xsc
  • 5,983
  • 23
  • 30
  • If you use the external test command (or his fork `[`), you must protect your operands with doubles quotes. See this answer for more details : http://stackoverflow.com/questions/19597962/bash-illegal-number/19598570#19598570 – Idriss Neumann Nov 03 '13 at 17:10
  • Seems to be working fine for me. Is this really a problem here, unless `date` fails to return something? Or does it depend on the version of Bash I'm using? – xsc Nov 03 '13 at 17:15
  • 1
    No problem with your `date` command which doesn't return a value with spaces for example. But it's a good practice that should be applied all the time. Otherwise you could use internal Bash instruction `[[` instead of `[` if you don't want to protect your operands. See my previous link to get more information. – Idriss Neumann Nov 03 '13 at 17:20
  • Just to be sure: I don't have to do it here but it's good practice? I'll amend my answer, of course. Thanks! – xsc Nov 03 '13 at 17:24
  • You don't have to do it (in this particular case) but you should ;) – Idriss Neumann Nov 03 '13 at 17:26
  • 2
    @xsc using appropriate quoting also makes your program able to run (depending on the shell implementation) very slightly faster, as the shell doesn't need to run string-splitting and glob-expansion on appropriately-quoted strings. – Charles Duffy Nov 03 '13 at 17:35
  • I really have to refresh my Bash-fu, don't I? Thanks for your advice! – xsc Nov 03 '13 at 17:37