based on barmar's suggestion, i was able to implement a workable solution. the following function can be used to rename an arbitrary bash function to another name.

renamefunction () {
    local oldname="$1"; shift
    local newname="$1"

    local definition="$(declare -f "$oldname")"
    if [[ $? -gt 0 ]]; then
        echo >&2 "renamefunction: $oldname is not a function"

    if declare -f  "$newname" >/dev/null 2>/dev/null; then
        echo >&2 "renamefunction: $newname is already defined"

    eval "$(echo "${definition/"$oldname"/"$newname"}")"
    # does not work for recursive functions (like "//" would), but also
    # doesn't break if $oldname is a substring of something else

    unset "$oldname"


  • the last line

    unset "$oldname"

    is optional — and without it, this becomes a "copy function" utility.

  • the pattern substitution would work for a recursive function if it were changed to the following (note the //):

    eval "$(echo "${definition//"$oldname"/"$newname"}")"

    however, this fails if the function name is a substring of something else within the definition. since recursion is relatively rare in shell scripts, i took the less brittle approach.

  • the quoting is correct, despite being too complex for the so syntax highlighter. (the quoting is also unnecessary, unless you like to play with $ifs.)

for completeness' sake, here's how i'm using this function:

# the default_cmd is the command to run if the command line could
# not be understood.  set the default_cmd to git, once; the user can
# change it at any time

# save the old command_not_found_handle for reuse
renamefunction command_not_found_handle __previous_command_not_found_handle

command_not_found_handle () {
    eval '"$default_cmd" $default_cmd_prefix_args "$@" $default_cmd_postfix_args'
    if [ $? -gt 0 ]; then
        __previous_command_not_found_handle "$@"
export default_cmd

command_not_found_handle is called by bash whenever it cannot find program or command that the user specified. it receives as its arguments the entire command-line.

this function tries to execute the command-line as a "sub command" of the given default_cmd. if it does not succeed, it tries the old command_not_found_handle

Related Query

More Query from same tag