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 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
}

~ by nico on October 11, 2011.

Leave a Reply

Your email address will not be published. Required fields are marked *