tree Command in Linux: Display Directory Structure

By 

Published on

6 min read

Displaying a nested directory structure in a Linux terminal with the tree command

The ls command shows the contents of one directory at a time. When you want to see how a whole project is laid out, running ls in every subdirectory gets old fast. The tree command solves this by listing a directory and everything below it as an indented tree, so you can take in the entire hierarchy at a glance.

This guide explains how to install tree and use it to display directory structures, limit depth, filter files, show sizes, and save the output to a file.

Installing tree

tree is a small utility that is not installed by default on most distributions, but it is available in the standard repositories.

On Ubuntu, Debian, and derivatives:

Terminal
sudo apt update
sudo apt install tree

On Fedora, RHEL, and derivatives:

Terminal
sudo dnf install tree

Once installed, verify the version:

Terminal
tree --version

Basic Usage

The general syntax of the tree command is as follows:

txt
tree [OPTIONS] [DIRECTORY]

When invoked without arguments, tree lists the current directory recursively. For example, running it inside a small Node.js project produces output like this:

Terminal
tree
output
.
├── package.json
├── README.md
└── src
    ├── app.js
    └── utils
        └── helpers.js

3 directories, 4 files

Each level of nesting is indented and connected with line-drawing characters, so helpers.js is clearly inside src/utils. The report line at the bottom counts everything in the listing, and since tree 2.1 that count includes the starting directory itself.

To list a different directory, pass its path as an argument:

Terminal
tree /etc/nginx

Limiting the Depth

On a large directory the default recursive listing can print thousands of lines. The -L option limits how many levels deep tree descends:

Terminal
tree -L 2 /var/log

With -L 2, tree shows the contents of /var/log and one level of subdirectories, then stops. This is usually the first option to reach for when a plain tree floods the terminal.

Showing Hidden Files

Like ls, tree skips hidden files by default. Use -a to include entries that start with a dot:

Terminal
tree -a
output
.
├── .env
├── .git
│   ├── config
│   └── HEAD
├── package.json
├── README.md
└── src
    ├── app.js
    └── utils
        └── helpers.js

4 directories, 7 files

Notice that .env and the .git directory now show up in the listing. Combining -a with -L 1 is a quick way to audit what actually lives in a directory, dotfiles included.

Listing Directories Only

When you only care about the folder structure and not the files, use -d:

Terminal
tree -d
output
.
└── src
    └── utils

3 directories

The files are gone and only the directory skeleton remains, which is handy for documenting a project layout.

Displaying File Sizes

The -s option prints the size of each file in bytes. In practice you will almost always use -h instead, which prints the sizes in human-readable units:

Terminal
tree -h
output
[4.0K]  .
├── [ 412]  package.json
├── [1.2K]  README.md
└── [4.0K]  src
    ├── [3.4K]  app.js
    └── [4.0K]  utils
        └── [ 890]  helpers.js

3 directories, 4 files

The size shown next to a directory is the size of the directory entry itself, not its contents. To get cumulative directory sizes, add --du:

Terminal
tree --du -h

With --du, each directory reports the total size of everything inside it, similar to the du command . This option reads the full hierarchy before printing, so it can take time and consume extra memory on a large directory tree.

Filtering by Pattern

The -P option lists only files that match a wildcard pattern. Quote the pattern so the shell does not expand it first:

Terminal
tree -P "*.js"

Directories are still shown even when they contain no matching files. Add --prune to remove the empty branches:

Terminal
tree -P "*.js" --prune
output
.
└── src
    ├── app.js
    └── utils
        └── helpers.js

3 directories, 2 files

Only the JavaScript files and the directories that lead to them remain. The patterns follow the same rules as shell globs; see our guide to Linux wildcards and globbing for the full syntax.

The -I option does the opposite and excludes matching entries. Multiple patterns are separated with |:

Terminal
tree -I "node_modules|.git"

This is the most common tree invocation in day-to-day work, since it hides the noise of dependency and VCS directories. In tree 2.0 and later you can also pass --gitignore to skip everything that the project’s .gitignore files exclude.

Printing Full Paths

By default each entry shows only its own name. The -f option prints the full path prefix instead:

Terminal
tree -f src
output
src
├── src/app.js
└── src/utils
    └── src/utils/helpers.js

2 directories, 2 files

Full paths are useful in saved listings because each entry keeps its context even when you view the output away from the original directory.

Sorting the Output

Entries are sorted alphabetically by default. The most useful alternatives are:

  • -t - Sort by last modification time, oldest first.
  • -r - Reverse the current sort order.
  • -v - Sort version strings naturally, so file2 comes before file10.
  • --sort=size - Sort by file size.

Note that -t places the oldest entries first, which is the opposite of what ls -t does. To see the most recently modified files at the top of each directory, combine it with -r:

Terminal
tree -t -r

Saving the Output to a File

The -o option writes the tree to a file instead of the terminal:

Terminal
tree -o structure.txt

The line-drawing characters are UTF-8 by default. If the file is destined for an environment that cannot render them, force plain ASCII connectors:

Terminal
tree --charset=ascii -o structure.txt

tree can also emit structured formats directly: -J produces JSON, -X produces XML, and -H <baseHref> produces a browsable HTML listing:

Terminal
tree -J -L 2 > structure.json

Quick Reference

CommandDescription
treeList the current directory recursively
tree -L 2Limit the listing to two levels
tree -aInclude hidden files
tree -dDirectories only
tree -h --duHuman-readable cumulative sizes
tree -P "*.js" --pruneOnly files matching a pattern
tree -I "node_modules|.git"Exclude matching entries
tree -fPrint full paths
tree -o file.txtWrite the output to a file
tree -JOutput JSON

Conclusion

The tree command turns a nested directory hierarchy into a single readable listing, and options such as -L, -I, and --du keep the output focused on what you actually need. If you want the same tree-style view for running processes instead of files, take a look at the pstree command .

Linuxize Weekly Newsletter

A quick weekly roundup of new tutorials, news, and tips.

About the authors

Dejan Panovski

Dejan Panovski

Dejan Panovski is the founder of Linuxize, an RHCSA-certified Linux system administrator and DevOps engineer based in Skopje, Macedonia. Author of 800+ Linux tutorials with 20+ years of experience turning complex Linux tasks into clear, reliable guides.

View author page