Linux Bash

Reference:
http://splike.com/wiki/Bash_Scripting_FAQ

Other resources:

Loop over some command's output

Loop breaking on any whitespace

for word in `cat somefile`
do
    echo Do something with $word here.
done

Loop breaking on lines (useful if directories have spaces in them)

find . -iname "*.jpg" | while read file
do
    echo Do something with $file here.
done

How do I check to see if an external executable is available?

Replace "jhead basename find mkdir mogrify cp" with the list of executables you want to check for. This snippet was taken from Thomas Hopfner's img2html script.

for tool in jhead basename find mkdir mogrify cp; do
    if ! type $tool >/dev/null 2>&1; then
        echo "ERROR: \"$tool\" not found."
        echo "       This is needed by $scriptname to work. Check your"
        echo "       \$PATH variable or install the tool \"$tool\"."
        exit 2
    fi
done

How do I get the short name of this script

 scriptname=`basename "$0"`

Or better:

 scriptname=

How can I debug?

To see the source as it executes through it, run your script like this:

 bash -v script.sh

or add this to the beginning of your script:

 set -v

To see the expressions evaluated as the script runs, execute your script like this:

 bash -x script.sh

or add this to the beginning of your script:

 set -x

How do I get my quoting right? (file paths with spaces; security concerns)

When executing anything, quote your variables if they are a single argument. Bash will quote the variable for you.

 mkdir -p "$destdir"

Don't quote if the argument variable might be empty, or if the variable is more than one parameter to the executable. In the following example, if "$recursive" is set, we get "find . '' -iname "*.jpg" …" and if "$recursive" is not set, we get "find . '-maxdepth 1' -iname "*.jpg" …" Neither of these is correct. In this case, we should not quote $recursive_param.

if [ "$recursive" ]
then
    recursive_param=""
else
    recursive_param="-maxdepth 1"
fi
# this is bad; $recursive_param should not be quoted
find . "$recursive_param" -iname "*.jpg" -or -iname "*.gif" -or -iname "*.png" | while read file
do
    # ...
done

When doing tests (if and case statements), quote your variables:

if [ ! "$force" ] && [ -e "$destfile" ]
then
    if [ "$verbose" ]
    then
        echo Skipping $destfile
    fi
fi

Concatenate strings?

 fullfilepath="$dirname$basename"

Or:

 fullfilepath="doesnt_change/${dirname}also_doesnt_change/${basename}.log"

( assuming $dirname includes a trailing '/' )

Substring function?

Use <code>${var:offset:length}</code>

myvar=abcdef
slice_of_myvar=${myvar:3:2}

Get a file's basename, dirname, extension, etc?

See bash/examples/functions/basename and bash/examples/functions/basename2

# set the 'file' variable first

# get extension; everything after last '.'
ext=${file##*.}

# basename
basename=`basename "$file"`
# everything after last '/'
basename=${file##*/}

# dirname
dirname=`dirname "$file"`
# everything before last '/'
basename=${file%/*}

Include another script (e.g. a script of functions)?

''Note: Test this; add full example''

 source util_functions.sh

Check to see if script is running as root?

if [ `id -u` != "0" ]; then
    echo "Sorry, you are not root."
    exit 1
fi