loading...

Create a Dynamic Prompt String in Bash

awwsmm profile image Andrew (he/him) ・2 min read

You may have seen some cool zsh prompts that show the name of the current Git branch in the prompt, like this one from oh-my-zsh:

I wanted to recreate something like that in bash and discovered that it's actually really easy to generate a dynamic bash prompt. Let's start with a boring old static prompt:

$ export PS1="\n$ "

$ ls
Applications      Documents         Dropbox           Library
Desktop           Downloads         Git               Movies

$ 

This sets my prompt to just a $ sign, with a newline before it so the output of the previous command isn't directly adjacent to the next prompt. To add a function to a bash prompt, all we need to do is include it as a subshell within the definition of PS1, making sure to escape the $ at the beginning of the subshell syntax, like so:

$ export PS1="\n\$(date)\n$ "

Thu 25 Jul 2019 14:27:23 IST
$ ls
Applications      Documents         Dropbox           Library
Desktop           Downloads         Git               Movies

Thu 25 Jul 2019 14:27:25 IST
$ 

Now, to check what branch we're on in a git project, we can do

Thu 25 Jul 2019 14:32:12 IST
$ git status
On branch my-test-branch
Your branch is up to date with 'origin/my-test-branch'.

nothing to commit, working tree clean

This gives us the current branch name in the first line. We can select that line with grep and parse it with sed:

Thu 25 Jul 2019 14:34:45 IST
$ git status | grep 'On branch' | sed 's/On branch / => /'
 => my-test-branch

But what happens if we're not within a git repo?

Thu 25 Jul 2019 14:35:06 IST
$ cd

Thu 25 Jul 2019 14:35:12 IST
$ git status | grep 'On branch' | sed 's/On branch / => /'
fatal: not a git repository (or any of the parent directories): .git

Oof, error text. Let's redirect all error output to /dev/null:

Thu 25 Jul 2019 14:35:26 IST
$ git status 2>/dev/null | grep 'On branch' | sed 's/On branch / => /'

There's now no output at all when the current directory isn't a git repo, so grep returns nothing and so does sed. Finally, let's add this to the prompt:

Thu 25 Jul 2019 14:35:36 IST
$ export PS1="\n\$(date)\$(git status 2>/dev/null | grep 'On branch' | sed 's/On branch / => /')\n$ "

Thu 25 Jul 2019 14:35:41 IST
$ cd Git/my_git_project/

Thu 25 Jul 2019 14:35:49 IST => my-test-branch
$ git checkout master
Switched to branch 'master'
Your branch is up to date with 'origin/master'.

Thu 25 Jul 2019 14:35:53 IST => master
$ 

That's it! You now have the same functionality as those fancy styled shells that display your current git branch. Just add some colour to this and you're good to go.

Discussion

pic
Editor guide
Collapse
cliffordfajardo profile image
Clifford Fajardo

Thank you for keeping it short and simple! This was a great starting point for me. Finally, a super great awesome example of using /dev/null!

I had been previously using zsh & oh-my-zsh for years, but wanted to keep things simple so I switched to bash a few weeks ago due to its widespread availability in every environment.

Collapse
msk61 profile image
Mohammed El-Afifi

github.com/ohmybash/oh-my-bash is oh-my-zsh equivalent for bash and provides this prompt out of the box.