My terminal theme used to be like this,

terminal them before

But I thought the prompt wasted so much space. And later I got an idea that I could clean the prompt every time I ran a command. I was using bash, one of solution is to use the preexec_invoke_exec function.

I use the following command to clean the last prompt chars:

echo -ne "\033[1A\033[K\033[1A\033[K\033[31;1m$ \033[0m"

So that the terminal is very clean, like this,

enter image description here

But now my problem is, there will be problem if I want to use multi commands in one line, say, when I use for i in ....

Here is the full version of the function in my .bashrc,

preexec () { echo -ne "\033[1A\033[K\033[1A\033[K\033[31;1m$ \033[0m"; echo -n "$1"; echo -ne "  \033[37;2m["; echo -n "$2"; echo -ne "]\033[0m\n"; }
preexec_invoke_exec () {
    [ -n "$COMP_LINE" ] && return  # do nothing if completing
    [ "$BASH_COMMAND" = "$PROMPT_COMMAND" ] && return # don't cause a preexec for $PROMPT_COMMAND
    local this_command=`history 1 | sed -e "s/^[ ]*[0-9]*[ ]*//g"`;
    local this_pwd=`pwd`; 
    preexec "$this_command" "$this_pwd"
trap 'preexec_invoke_exec' DEBUG
  • The Glyph Lefkowitz zsh trick - nice!
    – user44370
    Commented Dec 30, 2013 at 14:34
  • 2
    The easy solution starts with zsh Commented Dec 30, 2013 at 22:45
  • I missed your question in there... Commented Feb 4, 2014 at 23:39
  • @DavidHoelzer Well if you do for i in $(seq 1 10); do ls; done with his function, the output of the iterating commands gets "swallowed" so to speak. So OP wanted to sanitize the behavior while enabling that prompt. The reason why I support this is interest for awareness in the shell, usability, feedback and portability. The link I had put in my prior comment leads to the post on superuser - they went to the trouble of attributing this snippet, so it's a prototype which emulates native zsh functionality (which I think is interesting), in the form of a trap function here.
    – user44370
    Commented Feb 5, 2014 at 3:10

1 Answer 1


First preexec_invoke_exec has to be modified to prevent multiple executions of preexec. Also, modify preexec to take in account the actual number of lines in $PS1 :

preexec () { 
    # delete old prompt; one "\e[1A\e[K" per line of $PS1
    for (( i=0, l=$(echo -e $PS1 | wc -l) ; i < l ; i++ ))
        echo -ne "\e[1A\e[K"
    # replacement for prompt
    echo -ne "\e[31;1m$ \e[0m"
    echo -n "$1"
    echo -ne "  \e[37;2m["
    echo -n "$2"
    echo -e "]\e[0m"

preexec_invoke_exec () {
    [ -n "$DONTCLEANPROMPT" ] && return
    [ -n "$COMP_LINE" ] && return  # do nothing if completing
    [ "$BASH_COMMAND" = "$PROMPT_COMMAND" ] && return # don't cause a preexec for $PROMPT_COMMAND
    local this_command=`history 1 | sed -e "s/^[ ]*[0-9]*[ ]*//g"`;
    local this_pwd=`pwd`
    preexec "$this_command" "$this_pwd"

trap 'preexec_invoke_exec' DEBUG


In order for preexec to be run again, DONTCLEANPROMPT has to be either unset or set to ''. This is done with PROMPT_COMMAND, which is run just before the primary prompt is issued. Therefore preexec will be run once and only once for every command line.

  • Your solution solves the issue with the for loop! Thank you! There is a further inconvenience. What happens is that if you do ls on the command and you have the output, then you do another ls, you will see that the last line of the prior output gets erased... do you have an idea how to resolve that?
    – user44370
    Commented Feb 10, 2014 at 3:01
  • 1
    You are probably using a prompt with only a single line. Change the first echo in prexec to print "\033[1A\033[K\033[31;1m$ \033[0m", that is only one \033[1A\033[K (move 1 line up, delete till end of line) instead of two.
    – Adaephon
    Commented Feb 10, 2014 at 10:02
  • Flawless! Thank you very much for your solution and taking the time to explain. This solves OP's problem and debugs the solution even further. Makes it usable for everyone! Cheers!
    – user44370
    Commented Feb 11, 2014 at 6:08

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .