disclaimer: I am author of this indicator and it is written for this specific question
Update Oct 23,2018
The indicator now supports listing network shares. Thanks to mihaigalos
Update Oct 29, 2016
The indicator now has unmount functionality and aliases have been made unique by referring to UUID of each partition instead of block device name such as sda1
. See the related bug report
Update , Oct 8,2016
The indicator is now in version 2.0, has added a few features and has its own PPA.
To install from PPA, use the following steps in terminal:
sudo apt-add-repository ppa:udisks-indicator-team/ppa
sudo bash -c 'apt-get update && apt-get install udisks-indicator'
As mentioned in the release notes the features include:
- Icons for menu entries: each partition/device has appropriate icon attached to it. If the device is usb disk , removable media icon is used, if it's iso image - the optical disk icon is used, and obviously hard drive/SSD partitions have drive icons.
- Usage is now shown in percentage and human-readable values ( powers of 1024 ).
- Graphical representation of usage via usage bar ( big thanks to Mateo Salta for the idea )
- Preferences dialog : users can turn off certain fields that they do not want to see per each menu entry. This allows keeping indicator menu clean if there is a large amount of partitions attached. ( Thanks to Zacharee's request)
- Text spacing: with default Ubuntu font and Monospace fonts, the text entries are nicely spaced to have cleaner look and enhance readability of the information.
- Notification bubbles in case partition cannot be mounted
Below is the screenshot with default Ubuntu icon theme:

Ubuntu Kylin icon theme

With all optional fields off

Design choices and additional thoughts:
In the making of this indicator , I hoped to achieve a utility that would be suitable for advanced and casual users alike. I tried to address some of the issues that I've noticed the new users may have with handling command line tools. In addition, the utility strives to be multipurpose.
The Preferences dialog allows making the indicator as complex and/or as simple as the user desires. It was also a specific design decision to avoid having label in the top panel so that it doesn't take up too much of user's top panel space. In addition, this indicator strives to be multipurpose utility that allows mounting partitions as well as opening their respective directories. This can be used not just as disk usage utility , but also as navigation utility for quick opening of the directories.
It is also convenient for users to know which partition inhabits which disk, thus avoiding frequent confusion with mounting via command line utilities such as mount
. Instead it employs udisksctl
for that purpose ( as well as obtaining the information from UDisks2
daemon, hence the naming ). The only task that it does not perform is unmounting , and or this reason the Open Disks Utility
menu entry is included.
While originally I strived to make it similar to iStat menulet , the project diverged from this goal - the indicator is unique in it's design and purpose. I hope it will be found useful for many users and make their Ubuntu experience much more pleasant.
udisks-indicator (original answer)
Indicator for Ubuntu with Unity desktop to show disk usage

Overview
This indicator for Ubuntu with Unity allows easily view information about your mounted partitions. It strives to be visually similar to iStat Menu 3 menulet from OS X.
Entries are organized in order:
- Partition
- Alias ( if set by user )
- Disk Drive to which partition belongs
- Mountpoint of the partition ( directory )
- % Usage
Clicking on each partition entry will open the partition's mountpoint in the default file manager
The "Unmounted Partitions" menu lists all the partitions not currently mounted by the system. Clicking on any entry in that submenu will mount that partition automatically, typically to /media/username/drive-id
folder
The indicator uses default icons provided with the system, so the icon should be changing as you change the icon theme using Unity Tweak Tool or other methods
NOTE: if you want to add multiple aliases at the same time, instead of one by one via "Make Alias" option, you can do so via editing the ~/.partition_aliases.json
configuration file. The format is as follows:
{
"sda1": "Alias 1",
"sda2": "Alias 2",
"sdb1": "Alias 3"
}
Installation
PPA for easy installation is coming soon . . .
In the mean time, here are alternative steps:
cd /tmp
wget https://github.com/SergKolo/udisks-indicator/archive/master.zip
unzip master.zip
sudo install udisks-indicator-master/udisks-indicator /usr/bin/udisks-indicator
sudo install udisks-indicator-master/udisks-indicator.desktop /usr/share/applications/udisks-indicator.desktop
All these steps can be put into a nice little installation script:
#!/bin/bash
cd /tmp
rm master.zip*
wget https://github.com/SergKolo/udisks-indicator/archive/master.zip
unzip master.zip
install udisks-indicator-master/udisks-indicator /usr/bin/udisks-indicator
install udisks-indicator-master/udisks-indicator.desktop /usr/share/applications/udisks-indicator.desktop
Source code
Original source code (Version v1.0) with basic functionality of this indicator can be found below. For newest features , check GitHub repository for this project. Please report any feature requests as well as errors on GitHub.
The /usr/bin/udisks-indicator
:
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
#
# Author: Serg Kolo , contact: 1047481448@qq.com
# Date: September 27 , 2016
# Purpose: appindicator for displaying mounted filesystem usage
# Tested on: Ubuntu 16.04 LTS
#
#
# Licensed under The MIT License (MIT).
# See included LICENSE file or the notice below.
#
# Copyright © 2016 Sergiy Kolodyazhnyy
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included
# in all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
import gi
gi.require_version('AppIndicator3', '0.1')
from gi.repository import GLib as glib
from gi.repository import AppIndicator3 as appindicator
from gi.repository import Gtk as gtk
from os import statvfs
#from collections import OrderedDict
import subprocess
import shutil
import dbus
import json
import os
class UdisksIndicator(object):
def __init__(self):
self.app = appindicator.Indicator.new(
'udisks-indicator', "drive-harddisk-symbolic.svg",
appindicator.IndicatorCategory.HARDWARE
)
if not self.app.get_icon():
self.app.set_icon("drive-harddisk-symbolic")
self.app.set_status(appindicator.IndicatorStatus.ACTIVE)
filename = '.partition_aliases.json'
user_home = os.path.expanduser('~')
self.config_file = os.path.join(user_home,filename)
self.cache = self.get_partitions()
self.make_menu()
self.update()
def update(self):
timeout = 5
glib.timeout_add_seconds(timeout,self.callback)
def callback(self):
if self.cache != self.get_partitions():
self.make_menu()
self.update()
def make_menu(self,*args):
""" generates entries in the indicator"""
if hasattr(self, 'app_menu'):
for item in self.app_menu.get_children():
self.app_menu.remove(item)
self.app_menu = gtk.Menu()
partitions = self.get_partitions()
for i in partitions:
part = "Partition: " + i[0]
alias = self.find_alias(i[0])
drive = "\nDrive: " + i[1]
mount = "\nMountPoint: " + i[2]
usage = "\n%Usage: " + i[3]
item = part + drive + mount + usage
if alias:
alias = "\nAlias: " + alias
item = part + alias + drive + mount + usage
self.menu_item = gtk.MenuItem(item)
self.menu_item.connect('activate',self.open_mountpoint,i[2])
self.app_menu.append(self.menu_item)
self.menu_item.show()
self.separator = gtk.SeparatorMenuItem()
self.app_menu.append(self.separator)
self.separator.show()
self.unmounted = gtk.MenuItem('Unmounted Partitions')
self.unmounted_submenu = gtk.Menu()
self.unmounted.set_submenu(self.unmounted_submenu)
for i in self.get_unmounted_partitions():
# TODO: add type checking, prevent swap
part = "Partition: " + i[0]
alias = self.find_alias(i[0])
drive = "\nDrive: " + i[1]
label = part + drive
if alias:
alias = "\nAlias: " + alias
label = part + alias + drive
self.menu_item = gtk.MenuItem(label)
self.menu_item.connect('activate',self.mount_partition,i[0])
self.unmounted_submenu.append(self.menu_item)
self.menu_item.show()
self.separator = gtk.SeparatorMenuItem()
self.unmounted_submenu.append(self.separator)
self.separator.show()
self.app_menu.append(self.unmounted)
self.unmounted.show()
self.separator = gtk.SeparatorMenuItem()
self.app_menu.append(self.separator)
self.separator.show()
self.make_part_alias = gtk.MenuItem('Make Alias')
self.make_part_alias.connect('activate',self.make_alias)
self.app_menu.append(self.make_part_alias)
self.make_part_alias.show()
user_home = os.path.expanduser('~')
desktop_file = '.config/autostart/udisks-indicator.desktop'
full_path = os.path.join(user_home,desktop_file)
label = 'Start Automatically'
if os.path.exists(full_path):
label = label + ' \u2714'
self.autostart = gtk.MenuItem(label)
self.autostart.connect('activate',self.toggle_auto_startup)
self.app_menu.append(self.autostart)
self.autostart.show()
self.open_gnome_disks = gtk.MenuItem('Open Disks Utility')
self.open_gnome_disks.connect('activate',self.open_disks_utility)
self.app_menu.append(self.open_gnome_disks)
self.open_gnome_disks.show()
self.quit_app = gtk.MenuItem('Quit')
self.quit_app.connect('activate', self.quit)
self.app_menu.append(self.quit_app)
self.quit_app.show()
self.app.set_menu(self.app_menu)
def mount_partition(self,*args):
# TODO: implement error checking for mounting
return self.run_cmd(['udisksctl','mount','-b','/dev/' + args[-1]])
def get_mountpoint_usage(self,mountpoint):
fs = statvfs(mountpoint)
usage = 100*(float(fs.f_blocks)-float(fs.f_bfree))/float(fs.f_blocks)
return str("{0:.2f}".format(usage))
def get_partitions(self):
objects = self.get_dbus('system',
'org.freedesktop.UDisks2',
'/org/freedesktop/UDisks2',
'org.freedesktop.DBus.ObjectManager',
'GetManagedObjects',
None)
partitions = []
for item in objects:
try:
if 'block_devices' in str(item):
drive = self.get_dbus_property('system',
'org.freedesktop.UDisks2',
item,
'org.freedesktop.UDisks2.Block',
'Drive')
if drive == '/': continue
mountpoint = self.get_mountpoint(item)
if not mountpoint: continue
mountpoint = mountpoint.replace('\x00','')
drive = str(drive).split('/')[-1]
usage = self.get_mountpoint_usage(mountpoint)
part = str(item.split('/')[-1])
partitions.append((part,drive,mountpoint,usage))
except Exception as e:
#print(e)
pass
# returning list of tuples
partitions.sort()
return partitions
def get_mountpoint(self,dev_path):
try:
data = self.get_dbus_property(
'system',
'org.freedesktop.UDisks2',
dev_path,
'org.freedesktop.UDisks2.Filesystem',
'MountPoints')[0]
except Exception as e:
#print(e)
return None
else:
if len(data) > 0:
return ''.join([ chr(byte) for byte in data])
def get_unmounted_partitions(self):
objects = self.get_dbus('system',
'org.freedesktop.UDisks2',
'/org/freedesktop/UDisks2',
'org.freedesktop.DBus.ObjectManager',
'GetManagedObjects',
None)
partitions = []
for item in objects:
try:
if 'block_devices' in str(item):
drive = self.get_dbus_property('system',
'org.freedesktop.UDisks2',
item,
'org.freedesktop.UDisks2.Block',
'Drive')
if drive == '/': continue
mountpoint = self.get_mountpoint(item)
if mountpoint: continue
drive = str(drive).split('/')[-1]
part = str(item.split('/')[-1])
if not part[-1].isdigit(): continue
partitions.append((part,drive))
#print(partitions)
except Exception as e:
#print(e)
pass
partitions.sort()
return partitions
def get_dbus(self,bus_type,obj,path,interface,method,arg):
if bus_type == "session":
bus = dbus.SessionBus()
if bus_type == "system":
bus = dbus.SystemBus()
proxy = bus.get_object(obj,path)
method = proxy.get_dbus_method(method,interface)
if arg:
return method(arg)
else:
return method()
def get_dbus_property(self,bus_type,obj,path,iface,prop):
if bus_type == "session":
bus = dbus.SessionBus()
if bus_type == "system":
bus = dbus.SystemBus()
proxy = bus.get_object(obj,path)
aux = 'org.freedesktop.DBus.Properties'
props_iface = dbus.Interface(proxy,aux)
props = props_iface.Get(iface,prop)
return props
def make_alias(self,*args):
partitions = [ i[0] for i in self.get_partitions() ]
combo_values = '|'.join(partitions)
#print(combo_values)
command=[ 'zenity','--forms','--title','Make Alias',
'--add-combo','Partition','--combo-values',
combo_values,'--add-entry','Alias' ]
user_input = self.run_cmd(command)
if not user_input: return
alias = user_input.decode().strip().split('|')
existing_values = None
if os.path.isfile(self.config_file):
with open(self.config_file) as conf_file:
try:
existing_values = json.load(conf_file)
except ValueError:
pass
with open(self.config_file,'w') as conf_file:
if existing_values:
existing_values[alias[0]] = alias[1]
else:
existing_values = {alias[0]:alias[1]}
#print(existing_values)
json.dump(existing_values,conf_file,indent=4,sort_keys=True)
def find_alias(self,part):
if os.path.isfile(self.config_file):
with open(self.config_file) as conf_file:
try:
aliases = json.load(conf_file)
except ValueError:
pass
else:
if part in aliases:
return aliases[part]
else:
return None
def toggle_auto_startup(self,*args):
user_home = os.path.expanduser('~')
desktop_file = '.config/autostart/udisks-indicator.desktop'
full_path = os.path.join(user_home,desktop_file)
if os.path.exists(full_path):
os.unlink(full_path)
else:
original = '/usr/share/applications/udisks-indicator.desktop'
if os.path.exists(original):
shutil.copyfile(original,full_path)
self.make_menu()
def open_mountpoint(self,*args):
pid = subprocess.Popen(['xdg-open',args[-1]]).pid
def open_disks_utility(self,*args):
pid = subprocess.Popen(['gnome-disks']).pid
def run_cmd(self, cmdlist):
""" Reusable function for running external commands """
new_env = dict(os.environ)
new_env['LC_ALL'] = 'C'
try:
stdout = subprocess.check_output(cmdlist, env=new_env)
except subprocess.CalledProcessError:
pass
else:
if stdout:
return stdout
def run(self):
""" Launches the indicator """
try:
gtk.main()
except KeyboardInterrupt:
pass
def quit(self, data=None):
""" closes indicator """
gtk.main_quit()
def main():
""" defines program entry point """
indicator = UdisksIndicator()
indicator.run()
if __name__ == '__main__':
main()
The /usr/share/applications/udisks-indicator.desktop
[Desktop Entry]
Version=1.0
Name=Udisks Indicator
Comment=Indicator for reporting partition information
Exec=udisks-indicator
Type=Application
Icon=drive-harddisk-symbolic.svg
Terminal=false
Additional Info:
Ubuntu Mate 16.04 test:

Gnome users need an extension (KStatusNotifierItem/AppIndicator Support) to make the indicator behave properly:

/dev/sdb1
and its usage right next to it ? In percent or actual gigabytes ? – Sergiy Kolodyazhnyy Sep 26 '16 at 10:30