find | xargs idiom — or higher order shell functions
Here’s a shell function I’ve been using for over a decade. It takes three arguments: the name of a function to define, the name of a filter program (e.g., ‘grep’), and a find(1) expression, quoted. It defines a function by the given name that evaluates to find <directory arguments> | xargs <filter> <remaining-arguments>.
Here’s an example of how to use it:
% fsgen fmg grep '\( -name \*akefile -o -name \*akefile.in -o -name \*akefile.am -o \*.m4 -o \*.ac \);
% fmg . -- -O2
%
To make this work in KSH simple s/declare -a/set -A/.
My mnemonic for these shell functions is “find <type of thing> <filter>”. For example, fsg
means “find source grep”, while fseg
means “find source egrep”, and fmg
means “find makefiles grep”.
fsgen () {
typeset fname filter
fname=$1
shift
filter=$1
shift
eval "function $fname {
typeset fargs
declare -a fargs
while [[ \$# -gt 1 && \"\$1\" != -* ]]
do
fargs[\${#fargs[@]}]=\"\$1\"
shift
done
nsfind \"\${fargs[@]}\" $* -print | xargs $filter \"\$@\"
}
"
}
And the supporting nsfind function:
nsfind () {
typeset dargs
declare -a dargs
while [[ $# -gt 0 ]]
do
[[ "$1" = -* || "$1" = \! ]] && break
dargs[${#dargs[@]}]="$1"
shift
done
[[ ${#dargs[@]} -eq 0 ]] && dargs[${#dargs[@]}]=.
[[ "$1" = — ]] && shift
if [[ $# -eq 0 ]]
then
find "${dargs[@]}" \( \( -name SCCS -o -name CVS -o -name .hg -o -name .git \) -type d -prune \) -o –print
return $?
else
for i in "$@"
do
if [[ "X$i" = "X-print" ]]
then
find "${dargs[@]}" \( \( -name SCCS -o -name CVS -o -name .hg -o -name .git \) -type d -prune \) -o \( "$@" \)
return $?
fi
done
find "${dargs[@]}" \( \( -name SCCS -o -name CVS -o -name .hg -o -name .git \) -type d -prune \) -o \( \( "$@" \) –print \)
return $?
fi
}