Bash Scripting FAQ

From splike.com

Jump to: navigation, search

Other resources:


Contents


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 ${var:offset:length}

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
Personal tools