Home

Printing a Unix Directory Tree Diagram

There exists a program called tree that recursively prints a graphical tree diagram to the terminal. In the spirit of the Unix philosophy, however, there is another way to print a tree with the basic Unix programs [1].

find | sed 's;[^/]*/;|____;g;s;____|;  |;g'

Let us do a short walkthrough of what this command does.

A Walkthrough on Tree Printing

Using find alone yields the full path of every file on each line. Interestingly, it is difficult to recursively print all full paths on single lines with ls, which is why find is used instead. The output format of find is convenient to parse with sed.

$ find
.
./run_avg
./run_avg/Makefile
./run_avg/movAvg.c
./run_avg/test.m
./run_avg/ship
./run_avg/ship/Makefile
./run_avg/ship/generate
./run_avg/ship/test.m
./run_avg/ship/moving-average.pdf
./run_avg/ship/sine.png
./run_avg/ship/mine
./run_avg/ship/mine/result1024.csv
./run_avg/ship/mine/result1025.csv
./run_avg/ship/mine/result1000000.csv
./run_avg/ship/mine/result0.csv
./run_avg/ship/mine/result10000.csv
./run_avg/ship/mine/result100.csv
./run_avg/ship/generate.c
./run_avg/moving-average.pdf
./run_avg/sine.png
./run_avg/generate.c
./run_avg/moving-average.odt

Here, we pipe the full paths of all directories under our present working directory into sed, which replaces everything between the first forward slash and the last forward slash with lines depicting the tree.

$ find | sed 's;[^/]*/;|____;g;s;____|;  |;g'
.
|____run_avg
| |____Makefile
| |____movAvg.c
| |____test.m
| |____ship
| | |____Makefile
| | |____generate
| | |____test.m
| | |____moving-average.pdf
| | |____sine.png
| | |____mine
| | | |____result1024.csv
| | | |____result1025.csv
| | | |____result1000000.csv
| | | |____result0.csv
| | | |____result10000.csv
| | | |____result100.csv
| | |____generate.c
| |____moving-average.pdf
| |____sine.png
| |____generate.c
| |____moving-average.odt

Adding a Bit of Polish

Of course, the we can elaborate on this simple command, as demonstrated by the following polished command. In this command, I omit hidden files from the tree by removing lines with hidden files from the output of find. I then sort the lines alphanumerically with sort. The final result is piped into sed to draw the tree.

find | sed '/\/\./d' | sort -d | sed 's;[^/]*/;|___;g;s;___|;  |;g'

As with all things Unix, a shell script is usually helpful.

#!/bin/bash

# Prints Directory Tree



if [ "$1" == "-h" ]; then # show hidden files
  find | sort -d | sed 's;[^/]*/;|____;g;s;____|;  |;g'

elif [ "$1" == "-m" ]; then # expect manual input pipe
  sed 's;[^/]*/;|____;g;s;____|;  |;g'

else
  find | sed '/\/\./d' | sort -d | sed 's;[^/]*/;|___;g;s;___|;  |;g'

fi

A Comparison with the tree Program

tree is a properly written program that has all the options you could wish for. It is better that our little command in almost every way, especially in speed. lt is the shell script from before.

$ time lt > /dev/null; time tree > /dev/null

real	0m0.613s
user	0m0.628s
sys	0m0.104s

real	0m0.078s
user	0m0.056s
sys	0m0.020s

The output is almost exactly the same, except for the pretty box characters and the omission of the extra pipe characters indicating directory depth.

$ lt; tree
.
|___run_avg
|  |___generate.c
|  |___Makefile
|  |___movAvg.c
|  |___moving-average.odt
|  |___moving-average.pdf
|  |___ship
|  |  |___generate
|  |  |___generate.c
|  |  |___Makefile
|  |  |___mine
|  |  |  |___result0.csv
|  |  |  |___result1000000.csv
|  |  |  |___result10000.csv
|  |  |  |___result100.csv
|  |  |  |___result1024.csv
|  |  |  |___result1025.csv
|  |  |___moving-average.pdf
|  |  |___sine.png
|  |  |___test.m
|  |___sine.png
|  |___test.m
.
└── run_avg
    ├── generate.c
    ├── Makefile
    ├── movAvg.c
    ├── moving-average.odt
    ├── moving-average.pdf
    ├── ship
    │   ├── generate
    │   ├── generate.c
    │   ├── Makefile
    │   ├── mine
    │   │   ├── result0.csv
    │   │   ├── result1000000.csv
    │   │   ├── result10000.csv
    │   │   ├── result100.csv
    │   │   ├── result1024.csv
    │   │   └── result1025.csv
    │   ├── moving-average.pdf
    │   ├── sine.png
    │   └── test.m
    ├── sine.png
    └── test.m

3 directories, 19 files

Beyond Directory Trees

One drawback of the tree command is that it is purpose built and can not do anything else besides drawing directory trees (although it does just that very well). With our simple command we can pipe in more than just a directory list. We can use this to visualize things like dependencies in a C programming project or a simple family tree. A bit of awk should get whatever you need into the single line format that works so well with sed.

Notes

Written on the 21st of December in 2014

References

  1. Perderabo, "What command can display files in a tree: Post #2," http://www.unix.com/solaris/54552-what-command-can-display-files-tree.html , Accessed December 21, 2014.