BashScripts.org
http://bashscripts.org/forum/

Do something until I press a key
http://bashscripts.org/forum/viewtopic.php?f=16&t=882
Page 1 of 1

Author:  hermes [ Sun Aug 30, 2009 4:18 pm ]
Post subject:  Do something until I press a key

Hi to everybody!
I want to repeat an action (playing an audio file) until I press a key on my keyboard.
The latter can be achieved with read -n 1, but how do I insert the whole into a loop that waits for my input and plays in the meanwhile?
I hope I've been clear enough...

Thanks in advance!

Author:  fredrik.eriksson [ Mon Aug 31, 2009 1:28 am ]
Post subject:  Re: Do something until I press a key

Trap might do the trick. But I believe it only handles sig's.
http://linux.die.net/man/1/trap


Another solution could be something like this.
Code:
#!/bin/bash

program_i_want_to_run &
read tmp
pid=$(pidof program_i_want_to_run)
kill $pid


This will run the program, and then wait for your input into read, the $tmp variable is not of any concern since you just want to use read to "pause" the script.
kill $pid will kill all the instances with the same name, so this can be a bit risky if your application is named the same way as something you really want to keep.

Best regards
Fredrik Eriksson

Author:  hermes [ Mon Aug 31, 2009 3:44 am ]
Post subject:  Re: Do something until I press a key

Thanks for your reply.
Quote:
kill $pid will kill all the instances with the same name, so this can be a bit risky if your application is named the same way as something you really want to keep.

A solution for not killing all the instances with the same name may be to call pidof with -s, that returns only the last one.

Anyway, perhaps I didn't explain very well that I'd like to start looping a ring bell that plays until I press a key. Basically, I would need to break a the execution of a block of code when any input from the keyboard is received. I don't know if it's possible within a bash script...

I took a rapid look to trap, but I could not find it very useful for my purposes. A dirty trick should be:
Code:
echo "Press Ctrl+c to stop playing"
trap "kill $$" SIGINT
while true ; do
    aplay ringbell.wav
    sleep 1
done

This way I would avoid pressing Ctrl+c 2 times, one to kill aplay and one to exit the loop.

Another partial solution is:
Code:
while true ; do
    aplay ringbell.wav
    read -t 1 -n 1 && break
done

It plays the file and then waits for the user input. If no key is pressed within 1 second, sound file is played again, otherwise the loop breaks. The drawback is that I can only stop the loop whithin the short time of a second.

Regards

Author:  fredrik.eriksson [ Mon Aug 31, 2009 4:28 am ]
Post subject:  Re: Do something until I press a key

Well you could always do a little if check.

Code:
while [ true ]; do
   read -t 1 -n 1 tmp_var
   if [ ! -z $tmp_var ]; then
       exit 0
   fi
done


Not sure if this would work, since just pressing enter would make the $tmp_var contain "" which I think is the same as zero valued variable.

Problem with using read is that there is no way of checking if the variable is set in the first place. tmp_var="" is the same as not setting tmp_var, in contrast to other programming languages where setting "" inits the variable.
PHP or perl for example can check if the variable is set by using
PERL: if($var) { }
PHP: if(isset($var)) { }

Even thou both of these languages can declare content in a variable without first typecasting or defining the existance of a variable.

If anyone have a suggestion on how to check for a variables existance I would love to hear it :)

Anyway, back on topic.
script1.sh
Code:
#!/bin/bash
# Create a script to run ringbell.wav until script is killed. Also begin with returning the current PID
echo "
#!/bin/bash
pid=\$\$
echo $pid
while [ true ]; do
   aplay ringbell.wav
   sleep 1
done
" > /tmp/tmp.sh

# Execute and run the created script.
pid=$(bash /tmp/tmp.sh &)
# Wait for read.
read -n 1 -s tmp
# Kill the pid returned.
kill $pid
rm /tmp/tmp.sh


This could probably work as you want, but it's not fool proof... ctrl, alt and special keys that doesn't output a specific character won't be catched.

The best solution might be to either find a perl extension library which is built to handle keypresses or write a program in c or the like which can exit with a return value.

Anyway, going to stop ranting now and get back to work :P

Best regards
Fredrik Eriksson

Author:  hermes [ Mon Aug 31, 2009 2:46 pm ]
Post subject:  Re: Do something until I press a key

The temp file approach seems the best so far and it was my next option indeed.
Code:
# random seed and string
str=`echo $$ | md5sum | md5sum`
rand_str=${str:2:12}

# create a temp file with an unique name
tmp_file=/tmp/$rand_str

cat << EOQ > $tmp_file
#!/bin/bash
while true ; do
   aplay $sound
   sleep 1
done
EOQ

# Make it executable
chmod a+x $tmp_file

# Play the ring bell by executing the temp file
$tmp_file >/dev/null 2>&1 &

# Wait for a second to get the process id
sleep 1
pid=`ps x | grep $tmp_file | cut -d' ' -f 1`

echo "Press any key to stop playing the ring bell"

# read user input
read -n 1 -s tmp

# Kill the pid returned.
kill $pid >/dev/null

# remove temp file
if [[ -x $tmp_file ]] ; then
   rm -f $tmp_file >/dev/null 2>&1
fi

It's not fool proof too, but it does the trick!
Thanks for your help.

Author:  DarthWavy [ Tue Sep 01, 2009 6:03 am ]
Post subject:  Re: Do something until I press a key

fredrik.eriksson wrote:

If anyone have a suggestion on how to check for a variables existance I would love to hear it :)



this only returns non-empty if myvar is set
Code:
set | egrep '^myvar='


Also the following can be useful, causes bash to error when it tries to expand an unset variable
Code:
set -u

Page 1 of 1 All times are UTC - 6 hours
© 2000, 2002, 2005, 2007 phpBB Group • http://www.phpbb.com