An Intro to Functions
Functions are really scripts run in the current context of the shell. (This bit of techspeak means that a second shell is not forked to run the function; it's run within the current shell.) Functions really are full scripts in and of themselves, and allow all the flexibility and capability that entails.
You can create a function in a couple of different ways. You can just enter it into a file and source the file with the dot (.) command, either from the command line or in your startup scripts. You can also just enter the function at the command line. A function is only available in a session where it has been made available through one of these methods (or has inherited from its parent shell).
To create a function from the command line, you would do something like this:
$ gla() { > ls -la | grep $1 > }
This is a pretty simple function, and could be implemented as an alias as well. (There are reasons you might not want to do this; we'll get to those later.) As written, it displays a long listing of the local directory and greps for any matches for the first argument. You could make it more interesting by punching it through awk to find any matching files that are larger than 1024 bytes:
$ gla() { > ls -la | grep $1 | awk ' { if ( $5 1024 ) print $0 } ' > }
You can't do this as an alias, because you're no longer just replacing gla with the ls -la | grep. Since it's written as a function, there's no problem using the $1 (referring to the first argument to gla) anywhere in the body of your commands.
For a larger example, suppose you're working on two projects with two different CVS repositories. (Okay, it's a fair amount larger.) You might want to be able to write a function that allows you to set appropriate CVSROOT and CVS_ROOT variables, or to clear any values from these variables if the argument unset is given. It would also be nice if it would run cvs update for you if given the argument update. With aliases, you could approximate this, but only by running multiple aliases from the command line. Using functions, you could create a text file containing the following:
setcvs() { export done="no" if [ "$1" = "unset" ] # we want to clear all of the variables then echo -n "Clearing cvs related variables: " export CVSROOT="" export CVS_RSH="" export done="yes" echo "done" fi if ( pwd | grep projects/reporting /dev/null && [ "$done" != "yes" ] ) # if we're in the reporting area, and we're not already done then echo -n "Setting up cvs for reporting project: " export CVSROOT="issdata:/usr/local/cvs/" export CVS_RSH="ssh" export done="yes" echo "done" fi if ( pwd | grep projects/nightly /dev/null && [ "$done" != "yes" ] ) # if we're in the nightly area, and we're not already done then echo -n "Setting up cvs for nightly project: " export CVSROOT="/home/cvs/" export done="yes" echo "done" fi if [ "$1" = "update" ] # we want to update the current tree from the cvs server after # setting up the right variables then if [ -z "$CVSROOT" ] # if there is a zero length $CVSROOT (it has already been # cleared or was never set) throw an error and do nothing then echo "no cvs variables set ... check your cwd and try again" elif [ -n "$CVSROOT" ] # if there is a $CVSROOT try and do the update then echo "updating local tree" cvs -q update echo "done" fi fi }
Then you could enable the function and use it like this:
$ . ~/scripts/setcvs $ cd $ pwd /home/a257455 $ setcvs unset Clearing cvs related variables: done $ echo $CVSROOT $ echo $CVS_RSH $ cd projects/reporting/htdocs/ $ setcvs Setting up cvs for reporting project: done $ echo $CVSROOT issdata:/usr/local/cvs/ $ echo $CVS_RSH ssh $ cd ../../nightly/ $ setcvs Setting up cvs for nightly project: done $ setcvs update Setting up cvs for nightly project: done updating local tree done $ cd $ setcvs unset Clearing cvs related variables: done $ setcvs update no cvs variables set ... check your cwd and try again $
Functions can do a lot more than aliases. The function above shows a little bit of flow control, some error handling, and the ability to use variables. Certainly it could be improved, but it shows the point. Another big win is that functions can be reused in scripts, while aliases can't. For example, because the function above is saved in a file called ~/scripts/setcvs, you can write a script like this:
#!/bin/bash # a sample script # first source the functions . ~/scripts/setcvs # now go to the project directories and update them from cvs cd ~/projects/reporting/htdocs setcvs update cd - cd ~/projects/nightly setcvs update # now go back to where you were and unset any cvs variables. cd - setcvs unset