bash function Like you may have found many other programming languages, you will eventually find that you use certain code over and over in one of your script projects. And like other programming languages, bash provide for function definition. By predfining a function containing an often repeated block of code, you can save typing, ensure identical and consistant behaviour, and provide a single point of coding if you decide that the block of code needs to be fixed or modified. The general syntax of a bash function is : function myfun () { action-cmd[s] } myfun () { action-cmd } function myfun { action -cmd } In defining a function, you must either use the keyword "function" at the beginning of the definition or the "()" parentesis after the function keyword. You may use both but you must use at least one. Example : To define a function that performs the long listing of ls : function lsl { ls -l } To run it : % lsl Keep the following in mind when coding a function : * bash is an interpreted language, so the function must be defined before calling it. * You must call it to run it. It is possible to define a function and never use it. * A function is usually defined at the top of a shell script because all commands in the script are interpreted when they are encountered during execution. So, a function must be defined before being called. Placing the definition at the top also also makes it easy to find if you need to modify it. * A function may be redefined later in the script. That last interpreted definition is the one in effect. This is probably not a good idea. If you script contains conditional code, you may find you are not running the version of the function you think you are. * Don't define a function inside of a function. * Also, don't define a function inside a loop structure. * A function may call another function as long as both have been defined at the time they are executed. * A function may call itself. As with any recursion, make sure there is a way to prevent endless recursion. * A function may be defined at the command line for use in the current shell. * A function is not normally exported. However, you may put a function definition in your .bash_profile and/or .bash_rc file if you want it always available the command prompt. Alternatively, you may use : export -f function_name to export a defined function to a sub-shell. * In general, don't use the same name as a real command. Some versions of bash won't allow it. Invoking such a function can cause an endless loop condition. Example : function ls { ls -l } If the shell even allows this, when invoked, the command interperter will substitute the function with its definition and evaluate it. Upon find the ls -l, it will again substitute the ls with its function definition, etc., etc., and on and on. If you must define a function with the same name as a real command, specify the full path of the command : function ls { /bin/ls -l } export -f may refuse to export a function that is also a real command found in the command path. Do not redefine built-in commands such as "echo". In some cases, the alias feature of bash may serve this purpose. ****************** With those caviats in place, lets look at the general behaviour of the function. Notice that you do not include any variables in the parenthesis of the function definition. Rather than passing a value or variable into the function, the function may access any variables already in existance at the time of execution. Any changes a function makes to a variable is accessable through that variable when the function completes. A function may also define a new variable upon execution. Because the function is part the shell script running and not a separate sub-shell, the newly defined variable is accessable upon function completion to the rest of the bash script. However, there may be times when you do want a variable or at least its value inside the function to be accessable only inside the function. To make a variable "local" to the function, use "local" to set it. ************************** Experiment : function showvar { # change the value of an existing variable echo "d1 : " $d1 d1="from inside" echo "d1 : " $d1 # change the value of an existing variable, but keep it local echo "d2 : " $d2 local d2 d2="local in" echo "d2 : " $d2 # create a new variable and allow value to be be persistant echo "d3 : " $d3 d3="defined inside, persistant" echo "d3 : " $d3 # create a new variable and allow value, but keep it local echo "d4 : " $d4 local d4="defined inside, local" echo "d4 : " $d4 } d1="d1-outside" showvar echo "showvar called" echo "d1 : " $d1 echo "d2 : " $d2 echo "d3 : " $d3 echo "d4 : " $d4 *********************** Notice that variables not declared local persisit outside the function with the values set inside the function. Variables declared local inside the function are either not defined outside the function or retain their original values. The local modification is useful if you use a standard variable for a particular task both inside and outside of a function or in several functions. For example: You may have several functions that use "counter" to control the number of iterations of some action. However, unless each function is careful about initializing the "counter" variable, there is risk that a previously called function has left the "counter" variable set to a value that could adversely affect the currently called function. By declaring the "counter" local, any changes to its value disapear upon completion of function task. On the other hand, you may want to communicate the final value of the "counter" to the calling scrip upont completion of function task. There are several ways to pass information back to calling script. * You may use a variable that has not been defined as local. See the previous experiment for examples of this. * You may set a return code. Although the function is part of the script or current shell evironment, it does resemble a program when called. One thing it can do is set a status code upon completion. And just like any other command, you can access this status with the $? shell variable. The value returned must be an integer between 0 and 255. Mormally, 0 represents success and any other value represents failure. Just like any other command, the while, until, and if commands can test the return code of a function and act on it. However, you may choose to interpret the value of the return code any way you want. Experiment : prompt() { local ans echo -e "What to do? yes, no, quit [ynq] : \c" read ans case $ans in y|Y) return 0;; n|N) return 1;; q|Q) return 2;; } while 1 do echo "Want report on processes (y) or just who is on (n) " Prompt # Because $? is immediately reused by while to report its success, store # returned status of Prompt in a more permanent place and test that. status=$? # test User's choice on how to continue while $status -eq 0 do ps -u $USER Prompt status="$?" done if $status = 2 then exit 0; fi who }