basically tech

110 Colour-coded battery charge level and status in your bash prompt

Thursday 11th September, 2008

I still use a version of this script. The Linux kernel has changed somewhat so the script as it is below probably won't work. (Instead of /proc/acpi/battery/, direct the script towards /sys/class/power_supply/. And do make some other small changes.) I should update this.
Rob. April 2015.

I recently purchased a laptop, and having installed a proper OS, I found myself a little disappointed with the default battery meter provided by GNOME. Unless you mouse over the icon on the panel, it doesn't display exactly what charge level it is at. I am aware of the other options such as conky, gkrellm, screenlets, etc, but being the lazy sort, I consider it a long way to move your eyes! Since I'm the type who always has several terminals open, I thought it would be handy to display the charge level and status of the laptop battery in my shell prompt.

Firstly, I wrote a separate script to display the battery status. It's possible to write this into your ~/.bashrc as a function (which I also show how to do below), but I personally prefer a seperate script. The script had to fulfill certain requirements:

  • The script had to display the charge level as a percentage.
  • The script had to display it's results in colour, the reasons being that:
    1. I like a colourful prompt, and
    2. if the charge level gets too low, it's easier to notice if the displayed charge level changes colour.
    I've used green for 100% - 31% charged, yellow for 30% - 16% charged, and red for 15% charged or under.
  • The script also had to display the charge status, i.e. charging, discharging, or fully charged. After some experimentation I settled for a plus (+) for charging, a minus (-) for discharging, and an equals sign (=) for fully charged.
  • I noticed in earlier revisions of the script that, due to the way /proc displays the charge level, the script could sometimes output a charge level greater than 100%, so I wanted to include a fix for that.

Here is the script I came up with:

#!/bin/bash
#
# battery status script
#

BATTERY=/proc/acpi/battery/BAT0

REM_CAP=`grep "^remaining capacity" $BATTERY/state | awk '{ print $3 }'`
FULL_CAP=`grep "^last full capacity" $BATTERY/info | awk '{ print $4 }'`
BATSTATE=`grep "^charging state" $BATTERY/state | awk '{ print $3 }'`

CHARGE=`echo $(( $REM_CAP * 100 / $FULL_CAP ))`

NON='\033[00m'
BLD='\033[01m'
RED='\033[01;31m'
GRN='\033[01;32m'
YEL='\033[01;33m'

COLOUR="$RED"

case "${BATSTATE}" in
   'charged')
   BATSTT="$BLD=$NON"
   ;;
   'charging')
   BATSTT="$BLD+$NON"
   ;;
   'discharging')
   BATSTT="$BLD-$NON"
   ;;
esac

# prevent a charge of more than 100% displaying
if [ "$CHARGE" -gt "99" ]
then
   CHARGE=100
fi

if [ "$CHARGE" -gt "15" ]
then
   COLOUR="$YEL"
fi

if [ "$CHARGE" -gt "30" ]
then
   COLOUR="$GRN"
fi

echo -e "${COLOUR}${CHARGE}%${NON} ${BATSTT}"

# end of file

If you're going to use this script (at your own risk!), you should run it manually to test it before you continue. Your battery may be different, so if it doesn't work properly, have a look in /proc/acpi/battery and see if BAT0 should be BAT1 or something.

I use bash, so I had to edit my ~/.bashrc file to change my prompt. If you don't use bash, you'll have to figure out how to modify the prompt yourself. Remember to make a copy of your original ~/.bashrc before making any changes to it!

Note that in order to display the output from an external script or command in your bash prompt, you need to precede the command by a "\$" and wrap the command in normal brackets. If you don't the script will only run once (when you first login) and after that the output will never change. Here is an example of how to insert the output from the script into your prompt:

# ~/.bashrc
#
... (your other bashrc stuff) ...

PS1="[ \$(/path/to/script/battery_status.sh) ] \$ "

... (more of your bashrc stuff) ...

Which should present a prompt that looks like this:

Fully charged:

[ 100% = ] $

Charging:

[ 97% + ] $

Discharging:

[ 45% - ] $

Discharging, level quite low:

[ 27% - ] $

Discharging, level very low:

[ 13% - ] $

For something a bit more informative, you could try this:

PS1="[ \$(/path/to/script/battery_status.sh) ] \u@\h:\w \$ "

which should look something like:

[ 64% + ] rob@khitai:~ $

Using a function instead of a script

If you want to use a function instead of a script, what you need to do is to write the text of the script into your ~/.bashrc as a function, e.g.

# ~/.bashrc
#

battery_status()
{
BATTERY=/proc/acpi/battery/BAT0

REM_CAP=`grep "^remaining capacity" $BATTERY/state | awk '{ print $3 }'`
FULL_CAP=`grep "^last full capacity" $BATTERY/info | awk '{ print $4 }'`
BATSTATE=`grep "^charging state" $BATTERY/state | awk '{ print $3 }'`
...
(etc etc ... copy the remainder of the script)
...
if [ "$CHARGE" -gt "30" ]
then
   COLOUR="$GRN"
fi

echo -e "${COLOUR}${CHARGE}%${NON} ${BATSTT}"
}
... (your other bashrc stuff) ...

# Then call the function as you would any normal external script or command.
PS1="[ $(battery_status) ] \$ "

... (more of your bashrc stuff) ...

All this of course leads to other things. You could include all sorts of non-standard* information in your prompt, such as CPU temperature, free space in your home partition, etc. There's lots of scope for experimentation. :-)

* By non-standard I mean data which is not natively provided by bash. To see list of natively-provided prompt customisations, the bash man page has a comprehensive list under the section "PROMPTING". Also, see the link below.


Links

Bash Prompt How-to

Home