Python script to view largest sub-directories using ncurses
This simple Python script will show you the largest sub-directories (not files). When Enter
is pressed, the selected directory will be opened in the default file manager.
It’s a special utility that can be used to quickly filter through large directories of photos, videos, or other files.
#!/usr/bin/env python3
import curses
import os
import sys
from pathlib import Path
import subprocess
def format_size(size_bytes):
if size_bytes >= 1024*1024*1024:
return f"{size_bytes/(1024*1024*1024):.1f}GB"
return f"{size_bytes/(1024*1024):.1f}MB"
def get_dir_sizes(parent_dir):
dir_sizes = []
try:
with os.scandir(parent_dir) as entries:
for entry in entries:
if entry.is_dir():
size = sum(f.stat().st_size for f in Path(entry.path).glob('*') if f.is_file())
dir_sizes.append((entry.path, size))
except PermissionError:
return []
return sorted(dir_sizes, key=lambda x: x[1], reverse=True)[:30]
def main(stdscr, parent_dir):
curses.start_color()
curses.init_pair(1, curses.COLOR_BLACK, curses.COLOR_WHITE) # selected
curses.init_pair(2, curses.COLOR_GREEN, curses.COLOR_BLACK) # even
curses.init_pair(3, curses.COLOR_YELLOW, curses.COLOR_BLACK) # odd
curses.curs_set(0)
dirs = get_dir_sizes(parent_dir)
current_pos = 0
while True:
stdscr.clear()
height, width = stdscr.getmaxyx()
# Header
header = f"Directory overview for: {parent_dir} (Press 'q' to quit)"
stdscr.addstr(0, 0, header[:width-1])
# Directory listing
for idx, (path, size) in enumerate(dirs):
if idx >= height-2: # Leave room for header
break
name = os.path.basename(path)
size_str = format_size(size)
display = f"{name:<{width-15}} {size_str:>10}"
if idx == current_pos:
stdscr.attron(curses.color_pair(1))
stdscr.addstr(idx+2, 0, display[:width-1])
stdscr.attroff(curses.color_pair(1))
else:
color = curses.color_pair(2) if idx % 2 == 0 else curses.color_pair(3)
stdscr.attron(color)
stdscr.addstr(idx+2, 0, display[:width-1])
stdscr.attroff(color)
stdscr.refresh()
key = stdscr.getch()
if key == ord('q'):
break
elif key == curses.KEY_UP and current_pos > 0:
current_pos -= 1
elif key == curses.KEY_DOWN and current_pos < len(dirs) - 1:
current_pos += 1
elif key == ord('\n') and dirs:
curses.endwin()
subprocess.run(['xdg-open', dirs[current_pos][0]])
if __name__ == '__main__':
if len(sys.argv) != 2:
print("Usage: dir_size_browser.py <directory>")
sys.exit(1)
parent_dir = os.path.abspath(sys.argv[1])
if not os.path.isdir(parent_dir):
print("Error: Not a directory")
sys.exit(1)
curses.wrapper(main, parent_dir)
If this post helped you, please consider buying me a coffee or donating via PayPal to support research & publishing of new posts on TechOverflow