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 ================================================================