98

Often when I start looking at history of commands some of the characters from a command displayed aren't erased, for example:

What's happening:

prompt$ some_command
prompt$ some_commanother_command

What should have happened:

prompt$ some_command
prompt$ another_command

I can't erase those characters and bash ignores them when executing the command. They also disappear when a new prompt is being displayed (after pressing Enter for example).

I asked other people who work on Linux at my workplace and they said that they have that problem sometimes too, but they didn't have an idea on how solve that issue.

I have Ubuntu 11.10 and I'm using guake. Here is my PS1:

\e[0;31m\u \A ${PWD##*/}\e[0;32m$(parse_git_branch)\e[0;31m$\e[m

where parse_git_branch is

parse_git_branch () {
    git name-rev HEAD 2> /dev/null | sed 's#HEAD\ \(.*\)# (\1)#'
}

As far as I know my colleagues have that problem even with less "fancy" PS1.

korda
  • 1,571
  • As mentioned already, non-printable sequences need to be wrapped with \[...\] in order to let bash calculate the correct length of the prompt. However, what also seems to be important from my testing is if you have a multi-line prompt, the \r\n sequence should not go in the \[...\] wrapping. – Geraden Feb 19 '17 at 10:55

2 Answers2

109

Use \[...\] around the parts of PS1 that have length 0. It helps bash to get the length of the prompt right. Even with this measure, your command line can get spoiled when using multibyte characters (at least mine does). Hitting Ctrl+L also helps in such cases (but clears the screen at the same time).

choroba
  • 47,233
  • 4
    I modified my bashrc and now I have PS1="\\[\e[0;31m\\]\u \A \${PWD##*/}\\[\e[0;32m\\]\$(parse_git_branch)\\[\e[0;31m\\]$\\[\e[m\\] ". Kinda hard to understand when I'm looking at it but it seems that it helped. – korda Jan 11 '12 at 08:46
  • @korda I find using single quotes to remove the backslash doubling helps a lot. I also set the character sequences to variables, which helps a bit as well. My PS1 looks like PS1="${reset_color}[${cyan}\A${reset_color}]${reset_color}${user_color}\u@\h(\l)${white}:${blue}\W${reset_color}[${yellow}\$?${reset_color}]${white}"'\$'"${reset_color} " – jw013 Jan 11 '12 at 15:11
  • Ctrl-L only rarely helped me. But typing $ reset directly on the command line did the trick and brought my bash back to useable state. – syntaxerror Dec 10 '14 at 00:11
  • 2
    @NikosAlexandris: right at the beginning, \e[0m isn't enclosed in \[...\]. – choroba Mar 27 '15 at 12:09
  • 7
    Is there a bash bug report? This is a bug which has wasted too much of my time, and should be fixable in general (without PS1 hacks). – dhardy Nov 10 '16 at 15:53
  • @dhardy: What exactly is the bug? – choroba Nov 10 '16 at 15:56
  • 1
    @choroba that bash does some odd behaviour given incorrect PS1 instead of either doing the right thing or stopping with an error. It's a bit like the "undefined behaviour" in C etc.: allowed, but not likable, except in this case it should be fixable. – dhardy Nov 11 '16 at 09:22
  • @dhardy: Do you mean checking each character coming from various parts of PS1 for its non-zero length? Interesting idea. – choroba Nov 11 '16 at 09:24
  • This answer resolved my issue with a multiline prompt full of functions. I forgot to enclose 2 \e[xm with the \[...\] – Naoy Jul 22 '21 at 11:56
  • Thanks very much. I believe this fixed my issue. Is there a reference for this? Unfortunately these character sequences are not very googleable – David Sainez Jul 04 '22 at 19:46
15

You need to make sure you are escaping all of the non-printable characters.

Good

PS1="\[\e[36m\]\W ⇨ \[\e[m\] "

Bad

PS1="\[\e[36m\]\W ⇨ [\e[m\] "
user43633
  • 259
  • I'm getting this \[\e[36m\]\W ⇨ \[\e[m\] \[\033[m\033[1;37m\]\u\[\033[m\[\e[0;36m\]\] \w$(prompt_git)\n\[\033[m\033[1;37m\]$ \[\033[m\] as my prompt. U update PS1 in .bash_profile to the above but that didn't worked. – Steven Aguilar Apr 19 '19 at 14:31