Is there an equivalent to the Ubuntu tree command for Mac OS X?
- 157
- 7
- 7,423
- 9
- 26
- 31
13 Answers
You can get the tree command on macOS, too. If you have Homebrew:
brew install tree
If you do not have Homebrew installed, try one approach below.
Installing a package manager approach
Follow the instructions on these websites to install Homebrew, MacPorts, or Fink. Do not install more than one package manager at the same time!
Follow the prompt for whichever you installed.
For Homebrew: brew install tree
For MacPorts: sudo port install tree
For Fink: fink install tree
Installing from source approach
Install the Xcode command line tools by running
xcode-select --install.Change the Makefile to get it to work, which is also explained in @apuche's answer below. Commenting out the Linux options and uncommenting the macOS options should be enough.
Then, run
./configure, thenmake.Now you have to move the
treebinary file to a location that's in your executable path. For example:sudo mkdir -p /usr/local/bin sudo cp tree /usr/local/bin/treeNow edit
~/.bash_profileto include:export PATH="/usr/local/bin:$PATH"Reload the shell, and now
which treeshould point to/usr/local/bin/tree.
- 223,558
- 70
- 607
- 592
-
http://shaunchapmanblog.com/post/329270449/how-to-install-the-tree-command-on-mac-os-x also seems to have detailed instructions but may cause issues with llvm-gcc living under /Developer if you are running Xcode 4.x; a bit of fiddling around should do the trick. – Ahmed Masud Nov 21 '11 at 11:04
-
@MishaMoroshko Glad it worked. You'll find many programs on Homebrew, so if you ever miss something you had on Ubuntu or thought only Linux can have, Homebrew should help you! – slhck Nov 21 '11 at 22:15
-
"Problematic" how? – David Moles Jan 21 '15 at 17:54
-
1@DavidMoles Because simply running `make` on OS X doesn't work. First, you have to know how to install the Xcode command-line tools (or generally, have some idea about building software) and then you'll find that it errors out on an undefined symbol. So you have to do some adjustments to the makefile (as explained [here](http://andre-als.blogspot.de/2012/02/how-to-install-command-tree-for-mac.html)). Too much hassle IMO. – slhck Jan 21 '15 at 22:04
-
+1 for clarifying. :) (The Makefile edit is also documented in [this answer](http://superuser.com/a/448969/100451) below, btw.) – David Moles Jan 22 '15 at 17:38
-
1) Okay, you do have to install the Xcode Command Line Tools in order to compile programs that you want to install from source on OS X, but because the whole discussion is about a command line tool, namely `tree`, I would guess that most people have already done that, or can do that very simply. Personally, I hate package managers, so I try to install from source whenever I can. It doesn’t require any more effort to install the Xcode Command Line Tools than it does to install a package manager. Finally, suggesting that people need a package manager to install a simple little program like... – 7stud Apr 09 '15 at 02:32
-
`tree` is overkill. 2) In Yosemite 10.10.2, make does not error out--it gives a warning, which I just ignored, and the tree command installed just fine. But, the source code can be easily modified to get rid of the warning. See comments in the other answer. 3) When you download anything that you want to install, the first step is to read the README file, then the INSTALL file. The INSTALL file for `tree` asks you to uncomment certain lines in the Makefile depending on what OS you are using. Someone went to a lot of trouble to make that extremely easy. It certainly isn't problematic. – 7stud Apr 09 '15 at 02:32
-
4@7stud Many people know a few command line tools for very simple CLI tasks, and they may *not* know how to compile software. People sometimes struggle to understand what `./configure` and `make` exactly do and why those are needed in the first place. Or they don't want to deal with it. Or read any help files, for that matter. They'd rather do something like `apt-get install`. It's fine if you prefer installations from source (and I personally do, too), but you have to accept that there are solutions that are perceived easier by others, or perhaps even the majority of normal computer users. – slhck Apr 09 '15 at 06:56
-
@7stud I amended my answer to include more info for both ways of installing `tree`. – slhck Apr 09 '15 at 07:06
-
2*People sometimes struggle to understand what ./configure and make exactly do and why those are needed in the first place* I've been installing software from source for 15 years, and I have no idea what `./configure` and `make` do. I just know they are steps I need to perform in order to install software. I blindly read the README and INSTALL files, and I do whatever it says. – 7stud Apr 09 '15 at 17:08
-
This worked, but I had to also do [this](http://stackoverflow.com/a/26647594/2736496) in order for the link to take effect. – aliteralmind Nov 18 '15 at 17:38
-
Can you get the `tree` command to ignore certain file types e.g. `*.json`? – Dhruv Ghulati Aug 03 '16 at 17:51
-
1@DhruvGhulati Not that I know of, but you could inverse-`grep` it. Like `tree | grep -v 'json'` or similar. – slhck Aug 04 '16 at 08:20
-
@DhruvGhulati `tree --help` will list all the options, one of which is `-P pattern`, which lists only those files that match the pattern, and another is `-I pattern` which _omits_ the files that match the pattern. So `tree -I '*.json'` should do what you want. (Btw: I don't know what the pattern syntax is, but I found that this one worked: don't omit the single quotes.) – Steve Powell Feb 28 '17 at 10:33
-
I installed `teee` from brew and the file `/usr/local/bin/tree` do exist, but when I type `tree` the system say `-bash: tree: command not found`. What is the problem? Thanks in advance. – Evan Hu Jan 07 '19 at 03:15
-
@EvanHu When you run `echo $PATH`, is the `/usr/local/bin` path in there? Make sure this directory is part of your PATH and that you haven't overwritten it. Also make sure that the `tree` file is executable. In case of problems please ask a new question. – slhck Jan 07 '19 at 09:49
Not exactly the same, but one quick way on the Mac is:
find .
and that's it. It will list all file paths in the current directory as a list.
- 9,516
- 25
- 116
- 172
-
-
1
-
6I was only interested in going a few levels deep to show the directory structure so `find . -type d -maxdepth 2` worked for me – Matthew Lock Apr 21 '17 at 07:13
-
Better use `find *` if you don't want to see hidden files and directories. `tree` doesn't show hidden files and directories by default. – asmaier May 31 '18 at 14:36
-
-
1This will do nicely. Takes the wind out of the sails of those who answer each and every question "How do I install X on the Mac?" with "With homebrew, just say `brew X`". I never understood why anyone would like to maintain an extra package management system and be dependent on some people packaging things -- but to each his own. – András Aszódi Mar 26 '20 at 10:01
Or if your administrator won't let you install any of the brew, fink, port tools you can always build it from the source :
curl -O ftp://mama.indstate.edu/linux/tree/tree-1.5.3.tgz
tar xzvf tree-1.5.3.tgz
cd tree-1.5.3/
ls -al
Edit the Makefile to comment linux part and uncomment osx area:
# Linux defaults:
#CFLAGS=-ggdb -Wall -DLINUX -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64
#CFLAGS=-O2 -Wall -fomit-frame-pointer -DLINUX -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64
#LDFLAGS=-s
# Uncomment for OS X:
CC=cc
CFLAGS=-O2 -Wall -fomit-frame-pointer -no-cpp-precomp
LDFLAGS=
XOBJS=strverscmp.o
Optional: Forcing color output
And while you're at it, if you want to force tree to always colorize the output, you can always edit the main method of the tree.c file and add force_color=TRUE; before setLocale(LC_TYPE,"");
Finally hit make and you're done building tree for mac.
Tribute goes to Shaun Chapman for his original post on his blog.
- 53,069
- 19
- 162
- 212
- 381
- 3
- 4
-
Couldn't get to Shaun's website; thanks for the heads up on modifying the Makefile. – Paul Nathan Oct 26 '12 at 14:27
-
Specifically, you can add `force_color = TRUE;`. No semicolon and you get a compile error. – tgrosinger Sep 06 '13 at 15:55
-
1I've just built version 1.7 and instead of `setLocale` its `setlocale`. So in `tree.c`, you look for `setlocale(LC_TYPE,"")`; and thanks! – Avi Cohen May 02 '14 at 09:49
-
Great answer. Can you add a note on how to move it to `/bin` (or some path so that it can be used globally)? – Khanh Nguyen Oct 10 '14 at 04:57
-
1FYI, compiling 1.7.0 under Yosemite I got: `warning: format specifies type 'long' but the argument has type 'long long'`. The fix was to change a format specifier from `%9ld` to `%9lld`. – David Moles Jan 21 '15 at 18:02
-
@KhanhNguyen -- Personally, I put stuff like this in `~/bin`, and have a line `export PATH=~/bin:$PATH` in my `~/.bash_profile`. – David Moles Jan 21 '15 at 18:03
-
@DavidMoles, Same warning here. I ignored it, and `sudo make install` seemed to work. However, for the recored where is that format specifier? It's not in the Makefile. Ah, I found it in `tree.c`. – 7stud Apr 09 '15 at 01:42
-
It's not `setLocale`, it's `setlocale()` so you will need to search for the correct term. Installing from source is the way to go. The `Install` file tells you which lines to uncomment in the Makefile depending on your OS, so it couldn't be easer (you don't have to comment out the Linux options). However, this answer has too many errors. The colorizing seems random to me, so I would just skip it. – 7stud Apr 09 '15 at 01:55
There isn’t a formal tree command per se however you can do this:
Save the following script to /usr/local/bin/tree
#!/bin/bash
SEDMAGIC='s;[^/]*/;|____;g;s;____|; |;g'
if [ "$#" -gt 0 ] ; then
dirlist="$@"
else
dirlist="."
fi
for x in $dirlist; do
find "$x" -print | sed -e "$SEDMAGIC"
done
Change the permissions so you can run it:
chmod 755 /usr/local/bin/tree
Of course you may have to create /usr/local/bin:
sudo mkdir -p /usr/local/bin/tree
- 53,069
- 19
- 162
- 212
- 513
- 4
- 12
-
-
-
-
$x should be $dirlist shouldn't be quoted... because of the special expansion of "$@" – Ahmed Masud Nov 21 '11 at 11:24
-
@AhmedMasud I referenced this over here: http://superuser.com/questions/532156/how-do-i-print-a-tree-with-files-in-bash-for-windows#comment643537_532156 if you answer there I'll give you the marked answer – jcollum Jan 10 '13 at 23:10
-
Any idea how to color code the directories to a different color? Or reuse your directory listing colors? – Jen S. Sep 23 '14 at 05:46
-
1@JenS. of course you can simply change the find command to deal with that – Ahmed Masud Sep 24 '14 at 20:41
-
3I prefer this SED `SEDMAGIC='s;[^/]*/;|-- ;g;s;-- |; |;g'` which lines up the subdirectory pipe with the first letter of the parent directory and useds dashes instead of underscores. – Jason S May 24 '20 at 13:36
I found a simple solution here: http://murphymac.com/tree-command-for-mac/
So adding the following to your .bashrc, .bash_profile or any other place will make it work:
alias tree="find . -print | sed -e 's;[^/]*/;|____;g;s;____|; |;g'"
Now adding a tree command will print like this:
# ~/my-html-app [13:03:45]$ tree
.
|____app.js
|____css
| |____main.css
| |____theme.css
|____index.html
- 53,069
- 19
- 162
- 212
- 263
- 2
- 7
-
1Great little one-liner, but it works for the current directory only – András Aszódi Mar 26 '20 at 10:02
-
-
Sometimes I would like to draw a tree of another directory. Like I am in my home dir and want to see what's in, say, `/tmp`. Please understand that I like the elegance of this one-liner and upvoted your answer, just wanted to point out that this is not a full substitute for the "real" `tree` command, in case someone were looking for that. – András Aszódi Mar 26 '20 at 17:04
-
Thanks, @JasonS but I don't see it as the same answer as per the guidelines of StackExchange network. It's way different. – Shashank Agrawal May 25 '20 at 05:57
An alternative using find and awk:
#!/bin/bash
find . -print 2>/dev/null | awk '!/\.$/ { \
for (i=1; i<NF; i++) { \
printf("%4s", "|") \
} \
print "-- "$NF \
}' FS='/'
- 1,296
- 1
- 12
- 14
-
This lines up the subdirectory pipe with the first letter of the parent directory which I much prefer to the SED command repeated in multiple answers, which just indents the subdirectory two spaces, but gives four underlines before the parent directory. I also prefer the dashes. – Jason S May 24 '20 at 13:28
Adding a small point to @apuche's answer for OSX El Capitan rootless feature. make install fails since we are not allowed to write into /usr/bin directory.
vikas@MBP:~/Downloads/tree-1.7.0$ sudo make install
Password:
install -d /usr/bin
install: chmod 755 /usr/bin: Operation not permitted
install -d /usr/share/man/man1
if [ -e tree ]; then \
install tree /usr/bin/tree; \
fi
install: /usr/bin/tree: Operation not permitted
make: *** [install] Error 71
vikas@MBP:~/Downloads/tree-1.7.0$
To overcome this, just edit Makefile to have prefix = /usr/local
-
1Well, this technically works. But it’s invasive. So you could probably run `./configure --prefix=/usr/local` before running `make` and `make install` and it would achieve the same results. – Giacomo1968 Jan 12 '16 at 03:23
-
2@JakeGould Absolutely, I do use `prefix` in such scenarios. But there is no `configure` file in the latest version of [tree](http://mama.indstate.edu/users/ice/tree/) (1.7.0) now. The `INSTALL` file in the unzipped directory just says to use `make` and `make install` straightaway. – vikas027 Jan 12 '16 at 03:29
It's not as pretty as gnu tree ... but it's real easy to alias in bash ... You can even add a little color by tacking the G option on to osx's ls color.
alias tree='find . -type d | ls -lARG'
- 1,059
- 1
- 10
- 15
Here is a Ruby script solution that produces a nice Unicode tree along with useful metadata.
#!/usr/bin/env ruby
def tree_hierarchy( root, &children )
queue = [[root,"",true]]
[].tap do |results|
until queue.empty?
item,indent,last = queue.pop
kids = children[item]
extra = indent.empty? ? '' : last ? '└╴' : '├╴'
results << [ indent+extra, item ]
results << [ indent, nil ] if last and kids.empty?
indent += last ? ' ' : '│ '
parts = kids.map{ |k| [k,indent,false] }.reverse
parts.first[2] = true unless parts.empty?
queue.concat parts
end
end
end
def tree(dir)
cols = tree_hierarchy(File.expand_path(dir)) do |d|
File.directory?(d) ? Dir.chdir(d){ Dir['*'].map(&File.method(:expand_path)) } : []
end.map do |indent,path|
if path
file = File.basename(path) + File.directory?(path) ? '/' : ''
meta = `ls -lhd "#{path}"`.split(/\s+/)
[ [indent,file].join, meta[0], meta[4], "%s %-2s %s" % meta[5..7] ]
else
[indent]
end
end
maxs = cols.first.zip(*(cols[1..-1])).map{ |c| c.compact.map(&:length).max }
tmpl = maxs.map.with_index{ |n,i| "%#{'-' if cols[0][i][/^\D/]}#{n}s" }.join(' ')
cols.map{ |a| a.length==1 ? a.first : tmpl % a }
end
puts tree(ARGV.first || ".") if __FILE__==$0
You could modify the meta = … line to extract different metadata to display, hand-picking out the split pieces on the next line. With a little more work you could pass arbitrary ls arguments to select the metadata to show.
Sample output (looks nicer in the OS X terminal than the font on Stack Overflow):
phrogz$ tree UCC_IVI/
UCC_IVI/ drwxr-xr-x 510B Nov 20 11:07
├╴docs/ drwxr-xr-x 102B Nov 20 19:21
│ └╴CANMessages.txt -rwxr-xr-x 2.2K Nov 20 19:21
│
├╴effects/ drwxr-xr-x 204B Nov 19 17:19
│ ├╴Depth Of Field HQ Blur.effect -rwxr-xr-x 2.4K Nov 19 17:19
│ ├╴FXAA.effect -rwxr-xr-x 1.6K Nov 17 15:38
│ ├╴HDRBloomTonemap.effect -rwxr-xr-x 11K Nov 17 15:38
│ └╴SMAA1X.effect -rwxr-xr-x 4.4K Nov 19 17:19
│
├╴fonts/ drwxr-xr-x 136B Nov 17 15:38
│ ├╴Arimo-Regular.ttf -rwxr-xr-x 43K Nov 17 15:38
│ └╴OFL.txt -rwxr-xr-x 4.3K Nov 17 15:38
│
├╴maps/ drwxr-xr-x 238B Nov 19 17:19
│ ├╴alpha-maps/ drwxr-xr-x 136B Nov 17 15:38
│ │ ├╴rounded-boxes-3.png -rwxr-xr-x 3.6K Nov 17 15:38
│ │ └╴splatter-1.png -rwxr-xr-x 35K Nov 17 15:38
│ │
│ ├╴effects/ drwxr-xr-x 136B Nov 19 17:19
│ │ ├╴AreaTex-yflipped.dds -rwxr-xr-x 175K Nov 19 17:19
│ │ └╴SearchTex-yflipped.png -rwxr-xr-x 180B Nov 19 17:19
│ │
│ ├╴IBL/ drwxr-xr-x 136B Nov 17 15:38
│ │ ├╴028-hangar.hdr -rwxr-xr-x 1.5M Nov 17 15:38
│ │ └╴FieldAirport.hdr -rwxr-xr-x 1.5M Nov 17 15:38
│ │
│ ├╴icons/ drwxr-xr-x 238B Nov 19 17:19
│ │ ├╴icon_climate.dds -rwxr-xr-x 683K Nov 19 17:19
│ │ ├╴icon_music.dds -rwxr-xr-x 683K Nov 19 17:19
│ │ ├╴icon_navigation.dds -rwxr-xr-x 683K Nov 19 17:19
│ │ ├╴icon_phone.dds -rwxr-xr-x 683K Nov 19 17:19
│ │ └╴icon_surroundView.dds -rwxr-xr-x 683K Nov 19 17:19
│ │
│ └╴materials/ drwxr-xr-x 102B Nov 19 17:19
│ └╴spherical_checker.png -rwxr-xr-x 11K Nov 19 17:19
│
├╴materials/ drwxr-xr-x 102B Nov 19 17:19
│ └╴thin_glass_refractive.material -rwxr-xr-x 6.0K Nov 19 17:19
│
├╴models/ drwxr-xr-x 136B Nov 19 17:19
│ ├╴BokehParticle/ drwxr-xr-x 136B Nov 19 17:19
│ │ ├╴BokehParticle.import -rwxr-xr-x 739B Nov 19 17:19
│ │ └╴meshes/ drwxr-xr-x 102B Nov 19 17:19
│ │ └╴Mesh.mesh -rwxr-xr-x 1.1K Nov 19 17:19
│ │
│ └╴Glass_Button/ drwxr-xr-x 136B Nov 19 17:19
│ ├╴Glass_Button.import -rwxr-xr-x 1.2K Nov 19 17:19
│ └╴meshes/ drwxr-xr-x 136B Nov 19 17:19
│ ├╴GlassButton.mesh -rwxr-xr-x 44K Nov 19 17:19
│ └╴Icon.mesh -rwxr-xr-x 1.8K Nov 19 17:19
│
├╴scripts/ drwxr-xr-x 204B Nov 19 17:19
│ ├╴App.lua -rwxr-xr-x 764B Nov 17 15:38
│ ├╴CANSim.lua -rwxr-xr-x 29K Nov 17 15:38
│ ├╴ObjectWiggler.lua -rwxr-xr-x 3.7K Nov 19 17:19
│ └╴PathWiggler.lua -rwxr-xr-x 2.9K Nov 17 15:38
│
├╴states/ drwxr-xr-x 170B Nov 19 18:45
│ ├╴app-camera.scxml -rwxr-xr-x 2.4K Nov 20 11:07
│ ├╴app-navigation.scxml -rwxr-xr-x 590B Nov 19 18:32
│ └╴logic.scxml -rwxr-xr-x 4.2K Nov 19 18:59
│
├╴tests/ drwxr-xr-x 102B Nov 17 15:38
│ └╴interface-navigation.scxml-test -rwxr-xr-x 83B Nov 17 15:38
│
├╴UCC_IVI.uia -rwxr-xr-x 630B Nov 19 17:32
├╴UCC_IVI.uia-user -rwxr-xr-x 832B Nov 20 17:22
├╴UCC_IVI.uip -rwxr-xr-x 1.5K Nov 17 15:38
└╴UCC_Menu.uip -rwxr-xr-x 33K Nov 19 17:19
- 1,020
- 2
- 13
- 28
-
2Thanks very much for the lightweight solution! On OSX 10.9.5 (running stock Ruby 2.0.0), due to a 'no implicit conversion of true into String (TypeError)' error, I had to change the sixth line of the #tree method to read file = File.basename(path) + (File.directory?(path) ? '/' : '') – joel.neely Jul 16 '16 at 13:33
Install Xcode
Get Command Line Tools
xcode-select --install
- Install Homebrew
ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
- Install tree
brew install tree
- 53,069
- 19
- 162
- 212
- 109
- 3
Late to the game, but I had the same question. Due to workplace restrictions, I couldn't install a package from source or via a third-party package manager.
This is my implementation:
#!/usr/bin/env bash
#
# Faux tree command.
#
# Recursive directory/file listing of present working directory (PWD),
# with summary count of directories and files.
# Argument:
# Directory of interest,
# e.g.: tree /Users/foo/foo_dir
# Output:
# Recursive directory/file listing of named directory,
#
# Argument:
# Directory of interest, with user-defined level of resursive depth,
# e.g.: tree /System/Library 2
# Output:
# Recursive directory/file listing of named directory, stopping at
# user defined depth of recursion, e.g. 2
tree () {
[ -n "$2" ] && local depth="-maxdepth $2";
find "${1:-.}" "${depth}" -print 2> /dev/null | sed -e 's;
[^/]*/;|____;g;s;____|; |;g'
}
Simply add the function to /Users/foo/.profile or .bash_profile,
then refresh the profile with: source .profile or: source .bash_profile
- 152
- 4
-
-
tried your previous version and it kind of works. You must not have a new line after `s;` – phuclv Apr 28 '21 at 07:37
Installing broot very interesting command.
You will get the following:
- Searchability within the opened directory while navigating.
- Open your file or document with your default app. (similar to ranger) to exit use (:q)
Install on macOSX using HomeBrew
brew install broot
- 101
- 2