Display recursive directory listing in Terminal

Selecting List view in Finder displays files and folders in a recursive structure with sub folders and files appearing under their parent directories.

If you work in “Terminal”:terminal with any regularity, you know there are times when listing a directory structure in a manner similar to Finder’s List view would be handy, but there is no built in command to do so.

Before I switched to Mac OS X, I used Linux where I discovered a package called “Tree”:tree. The package consists of a single command that when passed a directory, displays a recursive tree-like listing of its content in ASCII form. The source for the package is freely available and can be downloaded and built in just a couple minutes.

Building Tree for Mac OS X

The following steps assume:

  1. Your using Mac OS X 10.6 Snow Leopard
  2. The latest “Xcode Tools”:devtools from the Snow Leopard DVD or downloaded from “Apple”:download are installed
  3. Your shell’s PATH variable includes /usr/local (if you don’t know why or how, see this Hivelogic “post”:hivelogic)
  4. You have experience running UNIX commands in Terminal

Change to or create a directory where you can download and unpack the source. I keep a ‘Projects’ folder to use for this kind of task.

cd ~/Projects/src/

Download and unpack the source code

The links and versions are current at the time of this writing. See the program “site”:tree for up to date information.

curl -O ftp://mama.indstate.edu/linux/tree/tree-1.5.3.tgz
tar xzvf tree-1.5.3.tgz

Now change to the source directory:

cd tree-1.5.3/

Modify the Makefile for Mac OS X

The source ships with a file called ‘Makefile’ that contains information used by the build process to compile Tree. By default, the source builds for the Linux OS and installs to /usr. Use your favorite text editor to change the file for Mac OS X.

Find the line that reads:

prefix = /usr

… and change to:

prefix = /usr/local

Find and uncomment (remove the leading ‘#’) the CFLAGS and XOBJS lines in the Mac OS X section of the Makefile so it looks like this:

# Uncomment for OS X:
CFLAGS=-O2 -Wall -fomit-frame-pointer -no-cpp-precomp

Compile and install

sudo make install

Assuming you did not receive any errors during the build process, you should be able to type the following and see a recursive listing of all the files and folders in the current directory:


If you want to see directories only, try this:

tree -d

That’s all there is.


Nautilus Script: Edit Remote Files (SSH) with Vim

My on again, off again love affair with “KDE (K Desktop Environment)”:kde is currently off (but that’s another story). I’m once again enjoying the simplicity of “Gnome (Gnome Desktop)”:gnome, and the elegance of “Nautilus (Nautilus file manager)”:naut.

The ability to graphically browse remote servers via SSH(secure shell) is great, but I found out that trying to edit a remote file chokes “Vim (Vim editor)”:vim. Apparently the netrw module does not handle an SSH URI(Uniform Resource Identifier), but rather prefers SCP(secure copy). So a quick nautilus-script to the rescue.

#!/usr/bin/env python

import os, sys
import re
import urllib

files = []

def unescape(uri):
    return re.sub(r'\s', r'\\ ', urllib.unquote(uri))

for file in os.getenv("NAUTILUS_SCRIPT_SELECTED_URIS", None).split("\n"):

    if re.match(r'^file://', file):
        files.append(unescape(re.sub(r'^file://', r"", file)))

    elif re.match(r'^ssh://', file):
        files.append(unescape(re.sub(r'^ssh://([^/]+)(/[^/]+){2}/(.*)$', r'scp://\1/\3', file)))


if files:
    os.system("""gvim """ + " ".join(files))


Still some work to do, but for now it’s simple and effective.


Bash: It’s the little things

The “Bash (Bash – GNU Project)”:bash shell always amazes me. I needed to create a “Maildir (Wikipedia: Maildir)”:maildir using the typical Maildir/cur, Maildir/new, Maildir/tmp structure and stumbled on this:

$ mkdir -m 0700 -p Maildir/{cur,new,tmp}

The -m and -p options are no-brainers, but the {cur,new,tmp} was new to me. It was easy to figure out what was going to happen… one command to create the Maildir directory, and the three subdirectories, I was simply unfamiliar with the syntax. A quick look at the “Bash (Bash – GNU Project)”:bash man page and I discovered “Brace Expansion (Bash Reference Manual: Brace Expansion)”:brace:

Brace expansion is a mechanism by which arbitrary strings may be generated.

A comma separated list between opening and closing braces is expanded by the shell including any preamble (in my case Maildir/) or postscript. Brace expansion can also generate ranges:

$ echo {1..10}
1 2 3 4 5 6 7 8 9 10

Cool, huh?