exa was a modern ls replacement: one Rust binary that gave you colorized output, a git status column, a tree view, and human-readable sizes without a single alias. The thing to know in 2026 is that exa is no longer maintained, and the drop-in replacement is eza, a community fork that picks up where it stopped. So the practical answer is: install eza, not exa.
# Debian 13+ / Ubuntu 24.04+ (older releases: use the deb.gierens.de repo)
sudo apt install eza
# Fedora 41 and older
sudo dnf install eza
# Fedora 42+ (dropped from the official repos; use the COPR or a release binary)
sudo dnf copr enable alternateved/eza && sudo dnf install eza
# Arch
sudo pacman -S eza
# macOS
brew install ezaeza keeps the same command surface as exa, so everything below works against either binary; just substitute the name. If you already have an exa install, your muscle memory and your aliases port over unchanged. The rest of this page is the flag reference, the migration, and the honest list of when plain ls is still the better tool.
Why exa, and why eza now
exa shipped sensible defaults that ls never had: a colored, column-aligned grid that distinguishes file types at a glance, sizes in K/M/G without needing -h, and a git-aware long view. It was popular enough to land in most distro repos.
Then development stalled. exa's last release was v0.10.1 in April 2021, and the project's own README now reads "exa is unmaintained, use the fork eza instead." (The repo is not formally archived only because the one person with rights to archive it is unreachable.) Open issues and pull requests sit unmerged, and some distributions have since dropped the package. eza is the maintained fork that took over: same author-facing behavior, same flags, ongoing bug fixes and new features (hyperlink support, better theming via a config file, more --git accuracy). If you are choosing today, choose eza. If you inherited an exa install, it still runs, but it will not get fixes.
I will write eza from here on. Replace it with exa mentally if you are on an older box that still has it.
The long view: eza -l
The command you will use most:
eza -lThat prints the long listing: permissions, size, modified date, and name, one file per line, colorized by type. It is the ls -l equivalent, but the size column is human-readable by default and the colors actually mean something.
Stack the common flags the way you would with ls:
eza -la # long view, including dotfiles
eza -la --git # ...plus a git status column
eza -lah # the -h here shows file headers, not "human sizes"One gotcha for ls muscle memory: in eza, -h is not "human-readable sizes" (those are already on); -h means --header, which prints a column header row. Sizes are human by default, so you rarely need to think about it.
The git status column: --git
eza -l --gitThis adds a two-character column showing each file's git status relative to the index and working tree: N for new/untracked, M for modified, staged versus unstaged shown in the two positions. It only does anything inside a git repository; outside one, the column is blank. It is the feature that made exa worth installing, and eza keeps it.
A worked example inside a repo with one tracked edit and one new file:
$ eza -l --git
-M .rw-r--r-- 1.2k techearl 5 Apr 10:14 readme.md
-N .rw-r--r-- 840 techearl 5 Apr 10:15 notes.txt
-- .rw-r--r-- 3.1k techearl 2 Apr 09:02 config.toml
The git column is the leftmost one, two characters wide: the first position is the staged state, the second is the unstaged state. readme.md is modified in the working tree (-M), notes.txt is new and untracked (-N), config.toml is clean (--). No git status needed for a quick glance.
The tree view: eza -T
eza -T-T (or --tree) prints the directory as a tree, the same shape the standalone tree command gives you, but with eza's colors, git awareness, and the ability to bolt on a long view. Limit the depth so you do not dump an entire node_modules:
eza -T --level=2 # two levels deep
eza -lT --level=2 --git # tree + long columns + git status
eza -T --git-ignore # tree, but skip files in .gitignore--git-ignore is the one I reach for most in a project root: it respects .gitignore, so the tree shows the files you actually care about instead of build output.
Icons and grouping
eza --icons--icons prefixes each entry with a Nerd Font glyph for its file type. It only renders correctly if your terminal font is a patched Nerd Font; without one you get tofu boxes. Worth setting up once, then it is on for good via an alias.
A couple more flags that earn their keep:
eza -l --group-directories-first # directories sorted to the top
eza -l --sort=modified # oldest first; add --reverse for newest first
eza -l --no-permissions --no-user # trim columns you do not needeza vs ls: the flag map
If you know ls, this is the translation table. Most ls short flags carry over, with a few that mean something different.
| Task | ls | eza |
|---|---|---|
| Long listing | ls -l | eza -l |
| Include dotfiles | ls -la | eza -la |
| Human-readable sizes | ls -lh | eza -l (default) |
| Sort by modified time | ls -lt | eza -l --sort=modified |
| Reverse sort | ls -lr | eza -l --reverse |
| Recursive | ls -R | eza -R |
| Tree view | (tree) | eza -T |
| Git status column | (none) | eza -l --git |
| Column header row | (none) | eza -lh / eza -l --header |
The standout difference is -h. On ls, -h is human-readable sizes; on eza, sizes are human by default and -h is --header. The other trap is that eza does not implement every obscure ls flag, so a script that leans on ls -1 --quoting-style=... will not port verbatim. For interactive use the map above covers almost everything.
Make it your default with an alias
Once you trust it, alias ls to eza in your shell rc so the new behavior is the default:
# ~/.bashrc or ~/.zshrc
alias ls='eza --group-directories-first'
alias ll='eza -la --git --group-directories-first'
alias lt='eza -T --level=2 --git-ignore'Keep the real ls reachable: command ls or \ls bypasses the alias when a script or a habit needs the original. That matters because aliasing ls to a tool that may not be installed everywhere is exactly how a copy-pasted shell snippet breaks on a server that has never heard of eza.
When plain ls is still the right call
eza is a better interactive ls. It is not a universal replacement, and a few situations call for the original:
- Scripts and portability.
lsis in POSIX and present on every Unix box, including minimal Alpine containers and stripped-down servers.ezais an extra install. Never aliaslstoezain a way that leaks into scripts; parse withfind,stat, or globbing rather than scrapingezaoutput anyway. - Machine-readable output. If you are piping into
awkorcut, the colorized, human-sizedezaoutput is harder to parse thanls -l --time-style=...or, better,statandfind -printf. Do not parselseither, but if you must,lsis the more stable contract. - A box where you cannot install anything. On a locked-down production host,
lsis what you have. Learnls -lhtrand move on. - Disk usage, not listings.
ezalists files; for "what is eating my disk" reach for a real disk tool. The duf disk usage df replacement covers the friendlierdf/dualternatives.
For day-to-day work in a terminal you control, eza wins on legibility. For anything that has to run somewhere else, write it against ls or the proper tool.
See also
- bat: a cat command replacement with syntax highlighting: the same "modern Rust rewrite of a core utility" idea applied to
cat, with paging and git gutter marks - duf: a friendlier df disk usage replacement: when the question is free space rather than a file listing
- find vs locate vs mlocate: for searching the filesystem by name instead of listing a single directory
- External: eza on GitHub, the maintained fork and its documentation.
- fzf: fuzzy-find what to feed it.
FAQ
Sources
Authoritative references this article was fact-checked against.





