Useful Shell Script Snippets

I've collected these snippets into this list mainly to satisify my own coding needs, I'm definitely not the originator of these techniques.

Basename replacement

This assumes that <path> is a variable that contains the path to be operated upon.${<path>##*/}

Dirname replacement

This assumes that <path> is a variable that contains the path to be operated upon.${<path>%/*}Note that unlike dirname this is a textual operation and if, for example, <path> evaluates to something that doesn't contain a "/" character then the entire contents of <path> will be returned, unlike dirname which will return a "." (i.e. the current directory).


For some reason there has never been a straightforward implementation of realpath available in all versions of unix, the closest I have come across is:$(readlink -m <path>)If your version of readlink doesn't work like this then you could try$(cd <path>; pwd)however this only really works if <path> is a folder. The main advantage over readlink is that "cd" and "pwd" are bash internal commands and readlink is an external utility. Another alternative is to invoke a language that does provide a wrapper for the realpath() call e.g.$(php -r 'echo realpath(<path>)')or$(python -c 'import os; print os.path.realpath(<path>);')Finally, a slightly more complex method is to wrap a call to realpath() in a small c program like this

 * rp.c: display the absolute path to a file or directory based on-
 * realpath.c: display the absolute path to a file or directory.
 * Adam Liss, August, 2007
 *  This program is provided "as-is" to the public domain, without express or
 *   implied warranty, for any non-profit use, provided this notice is maintained.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <libgen.h>
#include <limits.h>
int main( int argc, char *argv[] ) {
	char sPath[PATH_MAX + 1];

	if (argc < 2) {
		fprintf( stderr, "usage: %s PATH\n", basename( argv[0] ) );
		exit( 1 );

	printf( "%s\n", realpath( argv[1], sPath ) );
	return 0;

which can be compiled into a utility named "rp" and placed into a directory that is in your path. Assuming that this has been done then it can be used in your shell scripts like this:$(rp <path>)

Default value

There are two flavours to this one:${<param>:-<value>}and${<param>:=<value>}in the first version <value> is substituted if <param> is empty or unset, however <param> remains unchanged. In the second version if <param> is empty or unset then the <value> is assigned to <param> in any case <param> is then substituted; in this version <param> is altered. A related snippet is${<param>:?<message>}in this snippet, if <param> is empty or unset <message> is evaluated and sent to standard error and if the snippet is being executed as part of a script the script will exit.

Conditional execution

If you just want to execute a one (or a small number of commands) conditionally, without the full majesty ofif [[ <condition> ]] ; then <command>; fiyou can use[[ <condition> ]] && <command>this will execute <command> if <condition> is true. If you need to replaceif [[ ! <condition> ]] ; then <command> ; fiyou would use[[ <condition> ]] || <command>this will execute <command> only if <condition> is false. If you want to execute a sequence of commands you will need to terminate each command in the sequence with a semi-colon and surround the sequence with braces "{" and "}"{<command1>; <command2>; ...; }don't forget to terminate the final <command> with a semi-colon.

If you need both sides of a condition it's probably more efficient to use if ... then .. else ... fi rather than have two opposite conditional execution lines one after the other.