5

I wanted to customize my shell prompt to include the time. So, I did export PS1='\t\w\$'.

My prompt now looks like 18:57:37~$. I don't know how to prepend it with username@hostname.

Also, I don't know how to change the color of the each parameter for \t, \w, and so on.

After all the testing how do I set it back to the default?

Finally, where does the export line go? I looked in the ~/.profile, but there isn't the line export PS1='\t\w\$'.

3
  • Wouldn't that solve all your problems? bashrcgenerator.com/
    – Ziazis
    Dec 7, 2017 at 10:41
  • okay, at least would you tell me how to back to the default?? I think there are all the information in the manual, but I'm asking things because of the lack of summarizing for my specific task. I don't expect all answer is perfect for my question, but any answer helps me to trigger further research. Thanks.
    – Smile
    Dec 7, 2017 at 10:59

1 Answer 1

13

PS1 is set in your ~/.bashrc. This file contains settings which will be applied in every interactive shell. An interactive Bash shell is what you get when you open a terminal in Ubuntu, unless you have set a different default shell for your user.

In an interactive shell, we need a prompt, and it's nice if the prompt gives us some useful info, like the current working directory, the current user and the hostname, as the Ubuntu PS1 does.

Here are the lines which set PS1 in the default version of .bashrc for my system, /etc/skel/.bashrc

# uncomment for a colored prompt, if the terminal has the capability; turned
# off by default to not distract the user: the focus in a terminal window
# should be on the output of commands, not on the prompt
#force_color_prompt=yes

if [ -n "$force_color_prompt" ]; then
    if [ -x /usr/bin/tput ] && tput setaf 1 >&/dev/null; then
        # We have color support; assume it's compliant with Ecma-48
        # (ISO/IEC-6429). (Lack of such support is extremely rare, and such
        # a case would tend to support setf rather than setaf.)
        color_prompt=yes
    else
        color_prompt=
    fi
fi

if [ "$color_prompt" = yes ]; then
    PS1='${debian_chroot:+($debian_chroot)}\[\033[01;32m\]\u@\h\[\033[00m\]:\[\033[01;34m\]\w\[\033[00m\]\$ '
else
    PS1='${debian_chroot:+($debian_chroot)}\u@\h:\w\$ '
fi
unset color_prompt force_color_prompt

From PS1='${debian_chroot:+($debian_chroot)}\u@\h:\w\$ ' you can see that the escape codes for username and hostname are \u and \h respectively

zanna@toaster:~$ PS1="\u@\h"
zanna@toaster

If you want to add the time and current working directory:

zanna@toasterPS1="\u@\h \t \w "
zanna@toaster 10:43:32 ~ 

To get colours, you need to use the colour escape sequences. You can see some in the color_prompt assignment in .bashrc

PS1='${debian_chroot:+($debian_chroot)}\[\033[01;32m\]\u@\h\[\033[00m\]:\[\033[01;34m\]\w\[\033[00m\]\$ '

For example, \033[01;34m is blue:

PS1 assignment

Oops! Now the text after is blue as well... better change it back to white:

PS1 with color reassignment

We should surround colour assignments with escaped square brackets, otherwise Bash will think they are printing characters of the prompt and use them to calculate its size. This gives weird effects when you try to interact with your history, so here's the corrected version:

PS1="\[\033[01;34m\]\u@\h \t \w \[\033[00m\]"

When you have finished playing, you can return the prompt to default by closing the terminal and opening a new one ;) or by running

source ~/.bashrc

my PS1 back to normal

I set my PS1 like this using the code already in .bashrc, uncommenting #force_color_prompt=yes and changing the colour codes. Here you can see the lines I have changed to set it:

$ diff .bashrc /etc/skel/.bashrc 
46c46
< force_color_prompt=yes
---
> #force_color_prompt=yes
60c60
<     PS1='${debian_chroot:+($debian_chroot)}\[\033[01;32m\]\u@\h\[\033[00m\]:\[\033[01;35m\]\w\$\[\033[00m\] '
---
>     PS1='${debian_chroot:+($debian_chroot)}\[\033[01;32m\]\u@\h\[\033[00m\]:\[\033[01;34m\]\w\[\033[00m\]\$ '

(there are more lines changed after this, but they aren't relevant)

You could do the same, but add a \t into the color_prompt line somewhere, for example

PS1='${debian_chroot:+($debian_chroot)}\[\033[01;32m\]\u@\h \[\033[01;36m\]\t \[\033[00m\]:\[\033[01;35m\]\w\$\[\033[00m\] '

For a list of ANSI escape codes for colours and more stuff, see this guide to customising the prompt.


I neglected to answer the last part of your question.

Finally, where does the export line go? I looked in the ~/.profile, but there isn't the line export PS1='\t\w\$'

I'm not sure whether you expected running export VAR=val would cause your ~/.profile to be automatically modified. The export command never does this. Exporting a variable will only pass it into the environment of commands run from the current shell. When you exit the shell (and all of its child processes have exited), anything you exported from the shell is gone.

If you want to set an environment variable permanently, you generally need to add it to ~/.profile explicitly. Some scripts you might use to install software may modify your ~/.profile or other shell configuration files.

But PS1 does not need to be exported into the environment. At the start of my answer I said that in an interactive shell we need a prompt, and I meant that only interactive shells need prompts (because the prompt helps the user interact with the shell). No other command needs PS1.

You might be thinking that it could be useful for PS1 to be passed to any child shells of the current shell. When you start an interactive shell within a shell by running bash, the new shell will not inherit the shell variables of the calling shell; only its environment variables. So, to pass variables to a child shell, we should export them.

But exporting PS1 will usually* fail to pass its value to a child shell, because it is reset by the shell's configuration files, /etc/bash.bashrc and ~/.bashrc. So, closing the terminal (as I suggested earlier) is not necessary; even running bash will return your prompt to its usual form:

zanna@toaster:~$ export PS1='\t -> '
22:43:54 -> bash
zanna@toaster:~$ 

(if you exit this shell, the edited prompt comes back)

* I say usually, because, although non-interactive shells always unset PS1, an interactive Bash shell will preserve the value of PS1 if it is set. This isn't obvious, because as shown in the preceding example it typically gets reset by the configuration files. We can uncover it by changing PS1 and then starting a new shell that doesn't read our config files:

zanna@toaster:~$ export PS1='\t -> '
22:55:04 -> bash --norc
22:55:09 -> 

So, to conclude, there is no export line for PS1 in ~/.profile because PS1 is not an environment variable and has no business being one, since only interactive shells need it, and for the reason that interactive shells need PS1, it is set in ~/.bashrc, because unless told not to, all interactive Bash shells source ~/.bashrc, so ~/.bashrc doesn't need to export PS1 to be inherited by child shells (but if you do really want to export some value of PS1 other than the one in your .bashrc to a child shell, you can do so by preventing that shell from sourcing .bashrc).


I have been able to extend my answer thanks to Eliah Kagan, who explained how Bash treats PS1 here in chat and in more detail in this answer.

3
  • 3
    This is amazing. I feel like I own Ubuntu. Thanks :)
    – Smile
    Dec 7, 2017 at 11:17
  • 1
    1;36, Light Cyan is very cool stuff.
    – Smile
    Dec 7, 2017 at 12:11
  • Yes, I expected running "export VAR=val" would cause my ~/.profile to be automatically modified. I only understand your answer partially, but it is very helpful. Thanks :)
    – Smile
    Dec 9, 2017 at 9:07

You must log in to answer this question.

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