waseigo
DiskSpace - retrieve disk usage statistics for a given filesystem path
DiskSpace
Hi everyone, I needed this for a project I’ve been working on, and couldn’t find a simple solution that would work. The solutions in Check disk space inside elixir didn’t work for me.
Looking at how Exqlite deals with NIFs, I wrote a Makefile and then used Grok 3 with numerous rounds to generate the C file for a NIF. I then had GPT-5 and Gemini 2.5 Flash review it, then back to Grok 3 for implementing the suggested improvements, as Grok’s license permits licensing generated code permissively. Back and forth, again and again.
It should work on everything POSIX and on Windows, though I have only tested it on Debian 12. I don’t have Apple computers, and currently don’t run FreeBSD or NetBSD anywhere to try it out there.
What it does
It returns information about total, used, free, and available disk space, using native system calls for accuracy and performance. Optionally converts the results into human-readable strings with kibibytes etc. or kilobytes etc.
Returns disk space metrics as a map with keys:
:total— total size of the filesystem:used— bytes currently used:free— bytes free on the filesystem:available— bytes available to the current user (may be less than free due to permissions)
Provides both safe (stat/2) and bang (stat!/2) variants (with opts keyword-list options for human-readable output), the latter raising on errors.
Provides a humanize/2 function to which you can pipe the output of stat/2 and stat!/2 to generate human-readable output, if you don’t want to pass opts to those functions.
Usage example
iex(1)> DiskSpace.stat!("/tmp")
%{
available: 32389640192,
free: 43895349248,
total: 225035927552,
used: 181140578304
}
iex(2)> DiskSpace.stat("/tmp")
{:ok,
%{
available: 32389599232,
free: 43895308288,
total: 225035927552,
used: 181140619264
}}
iex(3)> DiskSpace.stat("/tmp", humanize: true)
{:ok,
%{
available: "30.17 GiB",
free: "40.88 GiB",
total: "209.58 GiB",
used: "168.70 GiB"
}}
iex(4)> DiskSpace.stat("/tmp", humanize: true, base: :decimal)
{:ok,
%{
available: "32.39 GB",
free: "43.90 GB",
total: "225.04 GB",
used: "181.14 GB"
}}
iex(5)> DiskSpace.stat!("/yolo/swag")
** (DiskSpace.Error) DiskSpace error: :realpath_failed
(disk_space 0.1.0) lib/disk_space.ex:86: DiskSpace.stat!/2
iex:5: (file)
Error-handling
stat/2returns{:ok, stats_map}or{:error, reason}stat!/2returnsstats_mapor raisesDiskSpace.Error
Reporting issues and opening PRs welcome.
- Package: disk_space | Hex
- Documentation: README — DiskSpace v1.0.0
- License: Apache-2.0
- Git repo:
Most Liked
NobbZ
Of course there is a runtime requirement… You have to add an entry to the applications deps list, and unless you set runtime: false your app will be loaded and started at runtime.
Please be aware that this is implicit, and compare it to the explicit adding to applications back before elixir 1.5.
waseigo
Actually, I just got disksup working. I had to add :os_mon to the :extra_applications in mix.exs… Oh well, live and learn!
To answer your question:
| Criterion | :disksup.get_disk_info/1 |
disk_space.stat/2 and stat!/2 |
|---|---|---|
| What it is | Function of a supervised process (:os_mon’s :disksup) |
Function relying on a NIF |
| Runtime requirements | :os_mon in :extra_applications in mix.exs |
Nothing |
| Need to compile? | No, part of Erlang | Yes |
| Returns | Returns total space, available space, and capacity (% of disk space used) | Returns total space, used space, free space, available to the current user |
| Return value type | 4-element tuple in list; first element: path as charlist; other elements: integers | {:ok, stats_map} or {:error, reason} (stat/2), stats_map or raises exception (stat!/2), where stats_map is a plain Elixir map with atom keys with: integer values (bytes) if option :humanize is false (default), string values (KiB, kB, etc.) if :humanize is true |
| Return units | kibibytes, percentage (as integers) | bytes (integers) or human-readable strings with humanize: true, either as KiB etc. (base: :binary, default) or kB etc. (base: :decimal) |
| Interval | 30 minutes (default), configurable with disk_space_check_interval |
N/A - checks upon invocation |
| Optional conversion to KiB, kB, etc. | No | Yes, with DiskSpace.humanize/2 |
| Works with UNCs on Windows? | Maybe not (“On WIN32 - All logical drives of type “FIXED_DISK” are checked.”) | Should work (not tested / cannot test) |
| Can alert you? | Yes, with :alarm_handler, signal :disk_almost_full, via :os_mon |
No, use it for “spot checks” |
| Well tested? | Yes | No (not yet) |
waseigo
Version 0.3.0 is up on Hex.pm.
- Tests now do not rely on mocking
- Requires OTP 27 on Windows
- Requires OTP 26 and above on recent Linux and on macOS
- Works on NetBSD 10.1, FreeBSD 14.3 and OpenBSD 7.7
- Does not work on DragonFlyBSD 6.4.1 due to OTP 25
- GitHub Actions workflow added for Linux, macOS, Windows
Supported Elixir and OTP versions
| OS | Arch. | Elixir | OTP | Builds and mix test passes? |
|---|---|---|---|---|
| Linux (Ubuntu/Debian) | amd64 | 1.14 | 25 | |
| Linux (Ubuntu/Debian) | amd64 | 1.15 | 26 | |
| Linux (Ubuntu/Debian) | amd64 | 1.16 | 26 | |
| Linux (Ubuntu/Debian) | amd64 | 1.17 | 27 | |
| Linux (Ubuntu/Debian) | amd64 | 1.18 | 27 | |
| Linux (Ubuntu/Debian) | amd64 | 1.18.4 | 28 | |
| macOS | arm64 | 1.14 | 25 | |
| macOS | arm64 | 1.15 | 26 | |
| macOS | arm64 | 1.16 | 26 | |
| macOS | arm64 | 1.17 | 27 | |
| macOS | arm64 | 1.18 | 27 | |
| macOS | arm64 | 1.18.4 | 28 | |
| Windows | amd64 | 1.14 | 25 | |
| Windows | amd64 | 1.15 | 26 | |
| Windows | amd64 | 1.16 | 26 | |
| Windows | amd64 | 1.17 | 27 | |
| Windows | amd64 | 1.18 | 27 | |
| Windows | amd64 | 1.18.4 | 28 | |
| NetBSD 10.1 | amd64 | 1.17.2 | 27 | |
| FreeBSD 14.3 | amd64 | 1.17.3 | 26 | |
| OpenBSD 7.7 | amd64 | 1.18.3 | 27 | |
| DragonFlyBSD 6.4.2 | amd64 | 1.16.3 | 25 |
Apologies to those behind the 40+ downloads of the prior versions, for whom it was only working on Linux. First time I’m dealing with a NIF (or GitHub Actions, for that matter)!







