(this will only work on recent bash versions)
#!/bin/bash
# as this uses bash-isms, better not use #! /bin/sh
on_error()
{
echo "error encountered in $BASH_COMMAND" >&2
}
trap on_error ERR
# inherit trap on error to functions and subshells
set -o errtrace
# don't continue after an error:
set -o errexit
more sofisticated on_error() function:
on_error()
{
case "$1" in
"") mailbody="error encountered in '$BASH_COMMAND' on line ${BASH_LINENO[0]}" ;;
*) mailbody="$1" ;;
esac
if tty > /dev/null
then
echo "ERROR: $mailbody" >&2
else
tty || echo "tty failed with $?"
mail -s "Probleme mit Notes SIT auf `hostname` in '$0'" $mailto <<EOF
$mailbody
EOF
fi
}
Assuming, you have a complete copy of directory dir on cdrom, mounted at /cdrom and want to delete them only after checking if the copy on CD is valid:
find dir -type f -print0 \ | xargs -0 -n 1 -I XXX sh -c "echo 'checking file \"XXX\"' ; diff -- 'XXX' /cdrom/'XXX' && rm -v -- 'XXX' || kill \"$PPID\""
Note: This solution copes even with filenames containg weird characters like $ and linefeeds.
If you want to clean up everything else afterwards without accidently removing left over files (as rm -r would do) use these commands:
find . -type l -print0 | xargs -0 rm -v find . -type s -print0 | xargs -0 rm -v find . -type p -print0 | xargs -0 rm -v find . -type d -empty -print0 |xargs -0 rmdir -p
Yes, it's paranoid. But I prefere being paranoid over loosing data
And no, this way you won't have a check whether all pipes, sockets and symlinks are the same in both directories. Talking about being paranoid, hmmmm?
script:
value=`awk ' $1 == "key" {print $2}' file.conf`
file.conf:
# key may occur in comments without causing problems key dies_ist_der_wert
will set key to “dies_ist_der_wert”
script:
value="`sed -ne 's/^[[:space:]]*key[[:space:]]*\([^#][^[:space:]]*\)[[:space:]]*\(#.*\|\)$/\1/gp' file.conf`"
file.conf:
# key may occur in comments without causing problems # all text between key and # or end of line without # leading or trailing whitespace is considered # the value (i.e. "dies ist der wert") key dies ist der wert # und dies ist ein Kommentar
for addpath in ~/bin
do
if echo "$PATH" | grep -qv "$addpath"
then
PATH="$PATH:$addpath"
fi
done
if man --path >/dev/null 2>&1
then
for addpath in ~/man
do
MANPATH="`man --path`:$addpath"
done
fi
get_cn()
{
( cline=`grep -m 1 '^cn:'`
while IFS="" read -r cont
do
case "$cont" in
" "*) cline="$cline""${cont# }" ;;
*) break ;;
esac
done
case "$cline" in
"cn: "*) echo "${cline#cn: }" ;;
"cn::"*) echo "${cline#cn:: }" | base64 -id ;;
*) echo "FAILURE" >&2 ; break ;;
esac ) < "$1"
}
ps --no-headers -o lstart -p "$pid"
read -r -s -p "Password: " pass echo
mkaliases()
{
( ls /opt/local/bin/ \
| while read item
do
if alias "$item" > /dev/null
then
alias $item | sed -e 's:^\(.*\)=\(.*\)$':"alias \1='\2':g"
else
echo "# alias $item='/opt/local/bin/$item'"
fi
done
alias | sed -E -e "s:^(.*)='?(.*[^'])'?$:alias \1='\2':g" ) \
| sort -u
}
#! /bin/sh
# Let's see which CVS version this is:
# $Id: shellscript_template.sh,v 1.4 2008/05/15 14:17:55 pjw Exp $
# set some default:
check_arg="foobar"
print_usage()
{
sed -e "s:^ ::g" << EOF # little trick to have HERE document indented
This is a lab lubba script to achieve foobar
It will skip files starting with [xyz].
Usage: ${0##*/} [-a|-b] [-c <arg1>] <file> [<file> ...]
Options:
-h : help - print this and exit
-v : verbose - print more messages
-q : quiet - print less messages
-a : add - some explanation what add means
-b : block - explain what block means
-c <arg1> : check - explain what check means and what arg
ist to be given (default "${check_arg}")
<file> : file(s) to act on
\$Id: shellscript_template.sh,v 1.4 2008/05/15 14:17:55 pjw Exp $
EOF
}
# # define functions for easy handling of -q (quiet) and -v (verbose) flags
echo_noquiet()
{
[ -z "$be_quiet" ] && echo "$@" ; # "$@" will echo all function args
}
echo_verbose()
{
[ -n "$be_verbose" ] && echo "$@" ; # "$@" will echo all function args
}
# just an example for a function:
# (see end of script for invocation)
multiply()
{
# take the two parameters of the fuction call and multiply them
#! /bin/sh
# Let's see which CVS version this is:
# $Id: shellscript_template.sh,v 1.4 2008/05/15 14:17:55 pjw Exp $
# set some default:
check_arg="foobar"
print_usage()
{
sed -e "s:^ ::g" << EOF # little trick to have HERE document indented
This is a lab lubba script to achieve foobar
It will skip files starting with [xyz].
Usage: ${0##*/} [-a|-b] [-c <arg1>] <file> [<file> ...]
Options:
-h : help - print this and exit
-v : verbose - print more messages
-q : quiet - print less messages
-a : add - some explanation what add means
-b : block - explain what block means
-c <arg1> : check - explain what check means and what arg
ist to be given (default "${check_arg}")
<file> : file(s) to act on
\$Id: shellscript_template.sh,v 1.4 2008/05/15 14:17:55 pjw Exp $
EOF
}
# # define functions for easy handling of -q (quiet) and -v (verbose) flags
echo_noquiet()
{
[ -z "$be_quiet" ] && echo "$@" ; # "$@" will echo all function args
}
echo_verbose()
{
[ -n "$be_verbose" ] && echo "$@" ; # "$@" will echo all function args
}
# just an example for a function:
# (see end of script for invocation)
multiply()
{
# take the two parameters of the fuction call and multiply them
# take the two parameters of the fuction call and multiply them
let "prod = $1 * $2"
echo $prod
}
# end of function definition
# --------------------------------
# start parsing command line arguments
# unset vars just in case
unset do_add
unset do_block
unset be_quiet
unset be_verbose
# init empty array
files=()
# check whether there are command line args left
while [ "$#" -gt 0 ]
do
case "$1" in
"-h") print_usage # print to stdout as this is no error
exit # normal exit as the user asked for help
;;
"-a") do_add=yes ;;
"-b") do_block=yes ;;
"-q") be_quiet=yes ;;
"-v") be_verbose=yes ;;
"-c") check_arg="$2" # use quotes to cope with whitespace
shift # do additional shift for parameter
;;
"-"*) echo "Unknown Option $1" >&2 # print error to stderr
print_usage >&2 # print to stderr as it was not expected
exit 42 # return error as it is one
;;
*) files=( "${files[@]}" "$1") # build shell arrays of filename to cope with
# multiple files even when containing whitespace
;;
esac
shift # drop first command line argument and shift other ones
done
# avoid any writes / changes if called without arguments
# so if there is no read-only default action, abord:
if [ -z "$do_add" -a -z "$do_block" ]
then
echo "Missing run option" >&2 # print errors to stderr
print_usage >&2 # print errors to stderr
exit 42 # indicate error my exit code != 0
fi
# abord if no files are given (never do any write operation by default)
if [ "${#files[@]}" -eq 0 ]
then
echo "Missing filenames" >&2 # print errors to stderr
print_usage >&2 # print errors to stderr
exit 42 # indicate error my exit code != 0
fi
echo_noquiet "check_arg is $check_arg"
# loop over array elements while respecting spaces in one element
for file in "${files[@]}"
do
echo " ========= "
echo "handling $file"
case "$file" in
[xyz]*) echo_noquiet "skipping file '$file' starting with x,y or z"
continue # jump to next
;;
*) echo_noquiet -n "do something with file"
[ -n "$do_block" ] && echo_noquiet -n " while blocking something"
[ -n "$do_add" ] && echo_noquiet -n " and add something"
echo_noquiet # finish line
echo_verbose "tell more about file '$file'"
;;
esac
done
echo
echo "end of parsing files"
echo
echo "this output is generated by a function:"
multiply 23 42