dui: like du, but interactive

2 minute read

Sometimes I just want to know why my computer’s disk is full. du will give me a firehose of information, but it’s slow and the results are hard to parse. I don’t need to know the size of every file, just which directories happen to be taking up a lot of bytes. I could download a file size visualizer from the internet, but that feels like overkill.

To make it easier to solve this problem, I wrote an interactive CLI utility that I’ve called dui (because it’s like du, but interactive). I wanted it to be fast, so I wrote it in Rust. It’s open source (MIT license).

Using dui

Since dui is published to crates.io, you can get it by running cargo install dui.

If you point it at a directory, it will give you an interactive tree view of all of the files in that directory, along with their size in bytes:

┗⊟ ".": 27.8 KB (100.00%)
  ┣⊞ "src": 23.5 KB (84.47%)
  ┣⊡ "README.md": 2.2 KB (8.00%)
  ┣⊡ "LICENSE": 1 KB (3.73%)
  ┣⊡ "Cargo.toml": 451 B (1.58%)
  ┗⊡ "rustfmt.toml": 247 B (0.87%)

You can navigate up and down different levels of the hierarchy and expand or collapse individual directories to dig deeper:

┗⊟ ".": 27.8 KB (100.00%)
  ┣⊟ "src": 23.5 KB (84.47%)
  ┃ ┣⊟ "cli": 17.9 KB (76.36%)
  ┃ ┃ ┣⊡ "render.rs": 9.1 KB (50.55%)
  ┃ ┃ ┣⊡ "handler.rs": 5.3 KB (29.66%)
  ┃ ┃ ┗⊡ "mod.rs": 3.4 KB (18.92%)
  ┃ ┣⊡ "crawl.rs": 3.8 KB (16.36%)
  ┃ ┣⊡ "main.rs": 1.5 KB (6.36%)
  ┃ ┗⊡ "lib.rs": 28 B (0.12%)
  ┣⊡ "README.md": 2.2 KB (8.00%)
  ┣⊡ "LICENSE": 1 KB (3.73%)
  ┣⊡ "Cargo.toml": 451 B (1.58%)
  ┗⊡ "rustfmt.toml": 247 B (0.87%)

You can also use it to check the number of files rather than the size in bytes1 by passing the --type num_files argument:

┗⊟ ".": 13 (100.00%)
  ┣⊟ "src": 8 (61.54%)
  ┃ ┣⊟ "cli": 4 (50.00%)
  ┃ ┃ ┣⊡ "mod.rs": 1 (25.00%)
  ┃ ┃ ┣⊡ "render.rs": 1 (25.00%)
  ┃ ┃ ┗⊡ "handler.rs": 1 (25.00%)
  ┃ ┣⊡ "lib.rs": 1 (12.50%)
  ┃ ┣⊡ "crawl.rs": 1 (12.50%)
  ┃ ┗⊡ "main.rs": 1 (12.50%)
  ┣⊡ "README.md": 1 (7.69%)
  ┣⊡ "rustfmt.toml": 1 (7.69%)
  ┣⊡ "Cargo.toml": 1 (7.69%)
  ┗⊡ "LICENSE": 1 (7.69%)

Implementation

The Rust ecosystem makes creating CLI utilities like really straightforward. The examples above are from running dui on its own source repo; you can see how little of my own code I had to write to build dui.

clap makes parsing CLI arguments as easy as defining a struct (and gives you --help and --version for free as a nice little lagniappe).

crossterm makes it super easy to build an interactive CLI that should hopefully be cross-platform out of the box.

ignore, despite the odd name, is a cross-platform parallelizable file tree walker, which meant that I didn’t need to write any code that actually interacted with the filesystem. It’s part of Andrew Gallant’s excellent ripgrep, which I’ve talked about previously.

Given how fast this was to set up, I feel like I can add a new tool to my command line problem-solving toolbox, for when tasks become too heavy for the other tools:

  1. run a one-off bash command
  2. write a bash script
  3. write a Python script
  4. write a one-file Go module
  5. write a Rust CLI <– new
  1. I recently had to do this because Emacs was complaining about having to maintain too many file watchers; turns out emacs-lsp was trying to watch all of the Bazel files in one of my Git submodules.