1

I've the following 5 second timer which prints an asterisk for each second.

timer () {
  i=1
  trap 'i=5' INT

  while [[ $i -le 5 ]]; do
    sleep 1
    printf "*"
    ((i+=1))
  done
}

Somehow the trap chunk seems a little hackish and I wonder if there's a more correct way to interrupt the entire loop (not just the current sleep cycle). I've tried:

trap 'print "foo"' INT

at various locations inside and outside the function, but as I alluded to before, that just interrupts the current sleep cycle.

Jolta
  • 2,620
  • 1
  • 29
  • 42
amorphousone
  • 65
  • 1
  • 4

2 Answers2

0

This works for me in bash:

#!/bin/bash

function timer {

    trap "break" INT

    i=0
    while (( ++i <= 5 )); do
        sleep 1
        printf '*'
    done
}

echo "Starting timer"
timer

echo "Exited timer"
echo "Doing other stuff...."

and this in ksh (note the different location of the trap statement):

#!/bin/ksh

function timer {

    trap "break" INT

    i=0
    while (( ++i <= 5 )); do
        sleep 1
        printf '*'
    done
}

echo "Starting timer"
timer

echo "Exited timer"
echo "Doing other stuff...."
ccbunney
  • 2,282
  • 4
  • 26
  • 42
0

Perhaps I'm missing something, but what's wrong with:

timer() {
  i=0
  while (( ++i <= 5 )); do
    sleep 1
    printf '*'
  done
}
Henk Langeveld
  • 8,088
  • 1
  • 43
  • 57
Dimitre Radoulov
  • 27,252
  • 4
  • 40
  • 48
  • Thanks for the response. I don't think you addressed the trap part of my question. Regardless of how I perform the loop, I'm using trap to break out of the loop (but not the surrounding script, which is not shown here for simplicity). However your loop suggestion looks better than mine. – amorphousone Dec 13 '11 at 19:32
  • Hi, @amorphousone! If you need to set i to 5 when you receive sigint, you're already using the right code (but I doubt you really need this). If you need to break the loop earlier (i.e. for some reason before the while condition evaluates false), you need to use the break command. – Dimitre Radoulov Dec 13 '11 at 21:14
  • Thanks for your suggestion. I'm aware of break, but the break condition would still rely on user input (ctl-c). How would I keep a loop going while reading for user input in the background? (I've googled a lot for that). – amorphousone Dec 14 '11 at 15:40
  • Hi @amorphousone, I'm not sure I understand what you mean by "rely on user input). As far as your second question is concerned, you could run the loop in background and read user input in foreground. – Dimitre Radoulov Dec 15 '11 at 14:12