Acabei de encontrar este problema também. É difícil dizer exatamente o que está acontecendo, mas parece que a segunda invocação é acionada dentro do contexto da função sendo chamada, então você poderia fazer:
! /bin/env bash
set -o functrace
function welcome { echo "Welcome :)"; }
function __debug_trap {
declare -F ${BASH_COMMAND%% *} >/dev/null
# funcname[0] is __debug_trap; funcname[1] is the next function on stack
if ! [[ "${BASH_COMMAND%% *}" == "${FUNCNAME[1]}" ]]; then
echo "[Running] ${BASH_COMMAND%% *}"
fi
}
trap __debug_trap DEBUG
welcome
echo not in function
#bash test.sh
#[Running] welcome
#[Running] echo
#Welcome :)
#[Running] echo
#not in function
A principal questão remanescente é que isso suprime incorretamente as chamadas recursivas diretamente; mas esses não são comuns no bash.