Infelizmente, não há uma variável de prompt PS
para controlar como os erros do bash são apresentados.
stderred é uma solução abrangente para esse tipo de problema, mas não funcionará sem modificações, pois tem uma exclusão codificada para bash
(leia mais por boas razões porque). Também é um pouco intrusivo (injeção de DLL).
hilite requer que você o use como wrapper, isso não funcionará para comandos embutidos como cd
.
Sua pergunta é feita especificamente sobre as mensagens de erro do bash, estas são enviadas para stderr
, mas stderr
também é compartilhado com qualquer processo filho, ou seja, com qualquer outro comando. Não tenho certeza se você quer distinguir os dois.
Um problema oculto aqui é que bash
escreve o prompt e sua entrada (echo) para stderr
. Para provar:
bash # start a sacrificial shell
exec 2> tmpfile # change stderr to a file
ls # you will see no prompt, and no command echo
...
exit # quit sacrificial shell
cat tmpfile # contains PS1 prompt, your commands (and any errors too)
Builtins chamam (ou pelo menos devem chamar) a função interna builtin_error()
para imprimir erros, isso chama incondicionalmente fprintf()
to stderr
, então as opções são poucas.
Sem saltar por aros ou aplicar patches em bash
, uma maneira simples de destacar erros é:
function _t_debug()
{
if [ "${BASH_COMMAND:0:6}" != "_t_err" ]; then
_lastcmd="$BASH_COMMAND"
fi
}
function _t_err()
{
local rc=$1 nn _type _argv
#shift; pipe=($*)
#if [ ${#pipe[*]} -gt 1 ]; then
# for ((nn=1; nn<=${#pipe[*]};nn++));do
# rc=${pipe[$((nn-1))]}
# echo -n "[$nn]=$rc ";
# ((rc >=128)) && echo -n "($((rc-128))) "
# done
#fi
read -a _argv <<< ${_lastcmd}
_type=$(type -t "${_argv[0]}")
if [ -n "$_lastcmd" ]; then
tput setf 4
printf 'Error %s: "%s"' "${_type}" "${_lastcmd:-unknown command}"
tput sgr 0
printf "\n"
fi
((rc >=128)) && echo "[rc=$rc ($((rc-128)))]" ||
echo "[rc=$rc]"
}
trap '_t_err $? ${PIPESTATUS[*]}' ERR
trap '_t_debug' DEBUG
Isso usa o bash DEBUG
trap para armazenar em cache cada linha de comando antes da execução e a ERR
trap para gerar os códigos de retorno se não forem zero. Porém, isso não acontecerá com determinados comandos internos (especificamente comandos compostos : while/case/for/if
e mais, veja a página man).
Eu uso uma variação disso no meu .profile
, embora eu use o pipe[]/PIPESTATUS[]
bit comentado acima, não é compatível com uma armadilha DEBUG como apresentado acima. Se você comentar o trap DEBUG
, poderá usá-lo para mostrar o código de retorno de cada comando em um pipeline.
(Além disso, como é referenciado, o gancho da função command_not_found
é bash-4.0 +.)