SHELLdorado Newsletter 3/2000 - September 24, 2000

================================================================
The "SHELLdorado Newsletter" covers UNIX shell script related
topics. To subscribe to this newsletter, leave your e-mail
address at the SHELLdorado homepage:

	http://www.shelldorado.com/

"Heiner's SHELLdorado" is a place for UNIX shell script
programmers providing

     Many shell script examples,
     shell scripting tips & tricks + more...
================================================================

Contents

 o  What's new at the SHELLdorado?
 o  Shell Tip: Easy interactive menus with "select"
 o  Shell Tip: How to execute a command in all subdirectories
 o  Shell Tip: How to set a "timeout" for commands

-----------------------------------------------------------------
>> What's new at the SHELLdorado?
-----------------------------------------------------------------

 o  The "SHELLdorado Links" section, one of the most popular
    pages of the SHELLdorado, has been revised. Despite the
    similar look, behind the scenes everything has changed ;-)

     -	The link page is now generated from link information
	stored in a mySQL database. This provides us with the
	opportunity of automated link checking, and subsequent
	less "broken" links

     -	All links have been re-visited, ranked and verified

     -  The entries have a consistent layout to simplify reading
        and browsing

    The page address is:

	http://www.shelldorado.com/links/

    Expect the section to grow considerably, soon!

    Thanks to Brian Hiles <brian_hiles@rocketmail.com> for his
    valuable comments on the first revisions of the page.

-----------------------------------------------------------------
>> Shell Tip: Easy interactive menus with "select"
-----------------------------------------------------------------

    The KornShell and BASH have a very useful (but hardly known)
    feature for writing easy interactive menus: the "select"
    loop.

    If we i.e. would like to have the user remove one file
    from the current directory interactively, we could use the
    following commands:

	PS3='Remove file: '	# Prompt string
    	select file in *
	do
	    echo "$file"	# or: rm -f "$file"
	    break		# only remove one file
	done

    This would print a selection menu like the following:

	1) file1.txt  3) file3.txt  5) selex
	2) file2.txt  4) file4.txt  6) tcpconn
	Remove file: _

    The script user just has to enter the number of the file.

-----------------------------------------------------------------
>> Shell Tip: How to execute a command in all subdirectories
-----------------------------------------------------------------

    With the large numbers of directories on a typical UNIX
    system, it can be very tedious to run a command in each
    of them.

    If we i.e. would like to remove all files named *.bak in
    all subdirectories, we would have to build a rather long
    "find" command line, i.e.

    	find . -name '*.bak' -print -exec rm -f {}

    How easy the same could be if we only had a command that
    would carry out a command recursively (i.e. named "global"),
    in a way that

    	global rm -f "*.bak"

    would suffice to remove the files in all subdirectories!

    The following script code does exactly this:

	# global - execute command in all subdirectories

    	exec 3<&0		# save standard input
	find . -type d -print |	# print all directory names
	    while read dirname
	    do
		(cd $dirname
		exec 0<&3       # restore standard input
		"$@"            # run command
		)
	    done
	exec 3<&-		# close file descriptor

    The rather cryptical "exec" lines ensure, that the command
    executed in each directory has the terminal at standard input
    (and not the directory list generated with "find").

    A full-featured script of the same name is available in
    the SHELLdorado "Scripts" section:

    	http://www.shelldorado.com/scripts/cmds/global

-----------------------------------------------------------------
>> Shell Tip: How to set a "timeout" for commands
-----------------------------------------------------------------

    Sometimes it is desirable to set a "timeout" for a command.
    If it does not complete within a certain period of time, it
    should be terminated automatically, and the script should
    continue.

    The following example shows how to terminate a program
    ("ping 127.0.0.1") automatically if it does not finish
    execution within five seconds:

	timeout=5               	# in seconds
	ping 127.0.0.1 & cmdpid=$!	# Command to terminate
	# Start "watchdog" process to terminate the command
	# after $timeout seconds:
	(sleep $timeout; kill -9 $cmdpid) &
	watchdogpid=$!
	wait $cmdpid			# wait for command
	kill $watchdogpid >/dev/null 2>&1

    The example script starts a "timed" command in the background
    ("ping 127.0.0.1"), and then starts another background
    process (the "watchdog") that will terminate the command
    in 5 seconds.

    It then waits for the "ping" command to terminate. If it
    terminates in time, the "watchdog" is terminated immediately,
    and the script continues.

    If the command does not terminate in time, the "watchdog"
    process will "kill" it after the timeout period, and the
    script will continue. The subsequent termination of the
    "watchdog" will not be necessary (but will do no harm,
    either).

    A more generic "timeout" script to monitor any arbitrary
    programs is available at the SHELLdorado "Scripts" section:

    	http://www.shelldorado.com/scripts/cmds/timeout

----------------------------------------------------------------
If you want to comment on the newsletter, or even want to submit
an article of your own, send a mail to

	mailto:heiner.steven@shelldorado.com

================================================================
To unsubscribe send a mail with the body "unsubscribe" to
newsletter@shelldorado.com
================================================================