Create a Dynamic Prompt String in Bash

Andrew (he/him) - Jul 25 '19 - - Dev Community

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

$ 
Enter fullscreen mode Exit fullscreen mode

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
$ 
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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 / => /'
Enter fullscreen mode Exit fullscreen mode

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
$ 
Enter fullscreen mode Exit fullscreen mode

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.

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .