A small Elixir library with a NIF for getting disk usage statistics for a given filesystem path. 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.
Features
- 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)
- Optional conversion of results from bytes into human-readable strings
- Supports Linux, macOS and Windows (via native NIFs)
- Might support the various BSDs (not tested)
- Provides both safe (
stat/2
) and bang (stat!/2
) variants (withopts
keyword-list options for human-readable output usinghumanize/2
), the latter raisingDiskSpace.Error
on errors
Installation
Add disk_space
to your list of dependencies in mix.exs
:
def deps do
[
{:disk_space, "~> 0.3.0"}
]
end
Supported Elixir and OTP versions
OS | Arch. | Elixir | OTP | Builds and mix test passes? |
---|---|---|---|---|
Linux (Ubuntu/Debian) | amd64 | 1.14 | 25 | ❌ errors with Erlang headers |
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 | ❔ Unknown / not tested |
macOS | arm64 | 1.14 | 25 | ❌ errors with Erlang headers |
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 | ❔ Unknown / not tested |
Windows | amd64 | 1.14 | 25 | ❌ errors with Erlang headers |
Windows | amd64 | 1.15 | 26 | ❌ errors with Erlang headers |
Windows | amd64 | 1.16 | 26 | ❌ errors with Erlang headers |
Windows | amd64 | 1.17 | 27 | ✅ |
Windows | amd64 | 1.18 | 27 | ✅ |
Windows | amd64 | 1.18.4 | 28 | ❔ Unknown / not tested |
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 | ❌ errors with Erlang headers |
Summary: requires OTP 27 on Windows, and OTP 26 and above on recent Linux, macOS, NetBSD, FreeBSD 14.3 and OpenBSD 7.7. Does not compile on DragonFlyBSD 6.4.2 yet due to OTP 25. PRs welcome to get it to build on OTP 25.
See also: GitHub Actions for Linux, macOS, Windows.
Build requirements
Since DiskSpace includes native code, you need the following build tools and development headers depending on your operating system:
Linux (amd64)
build-essential
(forgcc
,make
, etc.)erlang-dev
orerlang-erts-dev
(Erlang development headers)libc
development headers (usually installed by default)
Example on Debian and its derivatives:
sudo apt-get install build-essential erlang-dev
macOS (arm64)
xcode-select --install
clang
- Erlang installed via Homebrew or other means
NetBSD (amd64)
✅ Tested on version 10.1 and it works (Elixir 1.17.2, OTP 27).
# pkgin update
# pkgin install gcc gmake git erlang elixir
FreeBSD (amd64)
✅ Tested on version 14.3 and it works (Elixir 1.17.3, OTP 26).
# pkg update
# pkg install gcc gmake git erlang elixir ca_root_nss
DragonFlyBSD (amd64)
❌ Tested on version 6.4.2 and it does not work (Elixir 1.16.3, OTP 25).
# pkg update
# pkg install gcc gmake git erlang elixir
PRs welcome to get it to build on OTP 25.
OpenBSD (amd64)
✅ Tested on version 7.7 and it works (Elixir 1.18.3, OTP 27).
# pkg_add gcc-11.2.0p15 gmake git erlang-27.3.3v0 elixir-1.18.3
Windows (amd64)
choco install -y msys2
refreshenv
pacman -S -q --noconfirm pacman-mirrors pkg-config base-devel autoconf automake make libtool git mingw-w64-x86_64-toolchain mingw-w64-x86_64-openssl mingw-w64-x86_64-libtool
Also, Erlang installed with development headers.
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("/home/tisaak") |> DiskSpace.humanize(:decimal)
{:ok,
%{
free: "43.86 GB",
total: "225.04 GB",
used: "181.18 GB",
available: "32.35 GB"
}}
iex(6)> DiskSpace.stat("/yolo/swag")
{:error,
%{
info: %{errno: 2, errstr: ~c"No such file or directory"},
reason: :not_directory
}}
iex(7)> DiskSpace.stat!("/yolo/swag")
** (DiskSpace.Error) DiskSpace error: {:error, %{info: nil, reason: %{info: %{errno: 2, errstr: ~c"No such file or directory"}, reason: :not_directory}}}
(disk_space 0.1.1) lib/disk_space.ex:85: DiskSpace.stat!/2
iex:7: (file)
Error-handling
stat/2
returns{:ok, stats_map}
or{:error, info}
, whereinfo
is a map with populated:reason
(atom) and:info
(map ornil
) with more information, if provided by the NIF.stat!/2
returnsstats_map
or raisesDiskSpace.Error
with the{:error, info}
ofstat/2
as the message.
Alternatives
Add :os_mon
in :extra_applications
in mix.exs
, then use get_disk_info/1
of disksup
service.
Comparison to using :os_mon
/disksup
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? | Probably 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 | Yes, according to GitHub Actions |
Use of GenAI
c_src/disk_space.c
was incrementally generated/adapted by xAI’s Grok 3 model over multiple rounds of prompting for reviews and improvements that were suggested by Grok 3, GPT-5 and Gemini 2.5 Flash.
License
Apache-2.0
Documentation
For more details, see the documentation at https://hexdocs.pm/disk_space .
Discussion thread
ElixirForum: DiskSpace - retrieve disk usage statistics for a given filesystem path