Isso porque o bash acha que o prompt é mais longo do que é. A seqüência de escape \e[0;31m
, por exemplo, é sugada pelo terminal, que por sua vez torna o seguinte texto vermelho, mas bash não sabe disso. Portanto, você precisa dizer ao bash que essa sequência de caracteres não deve ser contada na duração do prompt, e você faz isso colocando-a em \[ \]
. Eu também recomendo usar tput em vez de sequências de escape de terminal de codificação.
red=$(tput setaf 1)
reset=$(tput sgr0)
PS1='\[$red\][\W]$\[$reset\] '
Veja BashFAQ 53 e Introdução dos códigos de terminal (ANSI / VT100) para mais.