GNU tree annoyed me so I fixed it

drhyde profile image David Cantrell ・2 min read

The tree utility is incredibly useful, but sometimes it can be just too verbose. Often you want to see a tree of some directory with exceptions - for example, you might have a sub-directory full of your project's dependencies that you have no interest in seeing.

To solve that problem tree has the -I option. My project's dependencies generally live in a local/ directory, so I can exclude it thus:

tree -I local

Now, what if I want to exclude something else as well, such as hiding my tests too. You would think that you could do this:

tree -I local -I t

But no. It only pays attention to one -I argument. Specifically, it only cares about the last one. If you want to ignore multiple directories you need to combine them into a pattern:

tree -I local|t

Except that doesn't work, the shell will interpret that as piping the output from tree -I local into t. You need to escape the pipe character:

tree -I local\|t

This is all a bit of a pain. Add to that that you can't set defaults in an environment variable or a configuration file, so I generally find myself forgetting to say -I at all and then having to do it again when my screen is filled with unwanted gibberish.

So I've fixed it with a shell function. That function will automatically apply any defaults that are in ~/.treerc (you can see mine here), and will combine multiple -I arguments into one.

It also lets you say -I \$FIGNORE as a special case to ignore anything mentioned in that specific environment variable. The env var is normally used to tell the shell what files to ignore when doing tab-completion, but I figure that, combined with per-project environment variables controlled by direnv it's a reasonable place to put such data. I may change that later though.

The argument processing is done in perl, as it's far easier to do in that language than in the shell, but it doesn't do a complete job because I'm lazy. In particular if you combine arguments in an invocation like this:

tree -ahI foo

then it won't spot that and give the -I in there the correct treatment. Patches welcome!

Posted on by:

drhyde profile

David Cantrell


I'm a perl grey-beard primarily interested in QA. I've been computering for 35 years and perling mostly on various Unixes for over 20 years.


Editor guide

Nice hack! You may be interested in checking out broot, an alternative to tree.