Terminate BASH For loop, that contains long sleep and other stuff, using any specific key

I've not had contact with this kind of tasks for a while, but I remember something like this used to work:

#!/bin/bash

trap break INT

for (( c=0; c<=$1; c++ ))
do  

# SOME STUFF HERE
#  data gathering into arrays and other commands here etc

    echo loop "$c" before sleep

    # sleep potentially for a long time
    sleep "$2"

    echo loop "$c" after sleep

done

#WRITE REPORT OUT TO SCREEN AND FILE HERE

echo outside

The idea is to use Ctrl-C to break the loop. This signal (SIGINT) is caught by the trap, which breaks the loop and lets the rest of the script follow.

Example:

$ ./s 3 1
loop 0 before sleep
loop 0 after sleep
loop 1 before sleep
^Coutside

Let me know if you have any problems with this.


The easiest way is to use Ctrl+C, since by default it gives the INT signal, which causes most applications to stop, and you can catch it in the shell.

To interrupt the whole loop at once, you could run it in a subshell, and exit when interrupted. Here, the trap is set only in the subshell, and only it exits.

#!/bin/bash

(
trap "echo interrupted.; exit 0" INT
while true; do
        echo "running some task..."
        some heavy task 
        echo "running sleep..."
        sleep 5;
        echo "iteration end."
done
)

echo "script end."

In some cases it is better to have a solution that does not interrupt "SOME STUFF HERE", and only breaks while the shellscript is waiting.

Then you can use the shell built-in command read with some options instead of sleep.

Try this shellscript,

#!/bin/bash

echo "Press 'q' to quit the loop and write the report"
echo "Press 'Enter' to hurry up (skip waiting this time)"

for (( c=0; c<=$1; c++ ))
do  

 echo "SOME STUFF HERE (pretending to work for 5 seconds) ..."
 sleep 5
 echo "Done some stuff"

#  data gathering into arrays and other commands here etc

# sleep potentially for a long time

#sleep $2
 read -n1 -st$2 ans
 if [ "$ans" == "q" ]
 then
  break
 elif [ "$ans" != "" ]
 then
  read -n1 -st$2 ans
 fi
done

echo "WRITE REPORT OUT TO SCREEN AND FILE HERE"

You find details about read with the command help read,

      -n nchars return after reading NCHARS characters rather than waiting
            for a newline, but honor a delimiter if fewer than
            NCHARS characters are read before the delimiter
      -s    do not echo input coming from a terminal
      -t timeout    time out and return failure if a complete line of
            input is not read within TIMEOUT seconds.  The value of the
            TMOUT variable is the default timeout.  TIMEOUT may be a
            fractional number.  If TIMEOUT is 0, read returns
            immediately, without trying to read any data, returning
            success only if input is available on the specified
            file descriptor.  The exit status is greater than 128
            if the timeout is exceeded