Uma possibilidade é criar uma função de wrapper que, ao mesmo tempo, imprima o comando e execute-o da seguinte forma:
debug() {
# This function prints (to stdout) its arguments and executes them
local args=() idx=0 IFS=' ' c
for c; do printf -v args[idx++] '%q' "$c"; done
printf "%s\n" "${args[*]}"
# Execute!
"$@"
}
Para que no seu script você possa fazer:
debug echo "$ARG"
Não há necessidade de mexer com a armadilha. A desvantagem é que ele adiciona algumas debug
de palavras-chave em todo o seu código (mas isso deve ser bom, é comum ter essas coisas, como assertes, etc.).
Você pode até mesmo adicionar uma variável global DEBUG
e modificar a função debug
assim:
debug() {
# This function prints (to stdout) its arguments if DEBUG is non-null
# and executes them
if [[ $DEBUG ]]; then
local args=() idx=0 IFS=' ' c
for c; do printf -v args[idx++] '%q' "$c"; done
printf "%s\n" "${args[*]}"
fi
# Execute!
"$@"
}
Depois, você pode chamar seu script como:
$ DEBUG=yes ./myscript
ou
$ DEBUG= ./myscript
ou apenas
$ ./myscript
dependendo se você quer ter a informação de depuração ou não.
Eu capitalizei a variável DEBUG
porque ela deve ser tratada como uma variável de ambiente. DEBUG
é um nome comum e trivial, portanto, isso pode colidir com outros comandos. Talvez chamá-lo de GNIOURF_DEBUG
ou MARTIN_VON_WITTICH_DEBUG
ou UNICORN_DEBUG
se você gosta de unicórnios (e provavelmente também gosta de pôneis).
Nota. Na função debug
, eu cuidadosamente formatei cada argumento com printf '%q'
para que a saída fosse corretamente excluída e citada de modo a ser reutilizável textualmente com uma cópia direta e cole . Ele também mostrará exatamente o que a casca viu, pois você poderá descobrir cada argumento (no caso de espaços ou outros símbolos engraçados). Essa função também usa a atribuição direta com a opção -v
de printf
para evitar subconsultas desnecessárias.