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).
Realpath
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>; fi
you can use[[ <condition> ]] && <command>
this will execute <command> if <condition> is true. If you need to replaceif [[ ! <condition> ]] ; then <command> ; fi
you 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.