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:
#CC=cc
CFLAGS=-O2 -Wall -fomit-frame-pointer -no-cpp-precomp
#LDFLAGS=
XOBJS=strverscmp.o

Compile and install

make
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:

tree

If you want to see directories only, try this:

tree -d

That’s all there is.

[terminal]http://en.wikipedia.org/wiki/Apple_Terminal
[tree]http://mama.indstate.edu/users/ice/tree/index.html
[devtools]http://developer.apple.com/technologies/xcode.html
[download]http://developer.apple.com/devcenter/mac/index.action
[hivelogic]http://hivelogic.com/articles/using_usr_local/

Use Mac OS X Automator and Services To Speed Up Repetitive Tasks

“Automator”:automator is one of best kept secrets in Mac OS X. It’s kind of like drag-and-drop scripting that lets you create workflows to automate and speed up repetitive tasks. In Snow Leopard, you can use Automator to create your own services that are accessible via the Services menu and can also be contextual, showing up when you right-click on an item like text selections or files and folders.

The Automator application lets you build a workflow by choosing from a collection of actions, some native to OS X, some installed by other applications, and dragging those actions into a workflow. There are actions that perform standalone tasks like copying a file to a specific folder, processing an image, or asking for input. If you need something more advanced there are actions that let you run shell commands, or even call other scripting languages like Python, Perl, or Apple’s own AppleScript. Combining these actions into a workflow lets you automate just about anything.

Addressing an Envelope Using Selected Text
I recently received a request to mail some additional information for a rebate I submitted several weeks ago. The email message contained the mailing address for the fulfillment center. Ordinarily, this means either hand addressing an envelope or going through several steps to launch Pages, choose a template, cut and paste the address, and print the envelope. It felt like I should be able to select the address and have an envelope automatically prepared and ready to print, but there is no built in way to do this.

Using Automator, I created a service that appears as a contextual menu item when working with selected text… in this case an address. In this workflow the Automator service is essentially a wrapper around AppleScript which does the heavy lifting here.

Automator envelope workflow

Here is the AppleScript that makes it happen.

on run {input, parameters}
	-- set the name of Envelope template to use
	set theTemplate to "Classic Envelope"
	-- set selection to first item of input list, ignore rest
	set theSelection to item 1 of input as text
	tell application "Pages"
		-- launch Pages without "Template Chooser"
		launch
		try
			make new document with properties {template name:theTemplate}
		on error
			-- display msg if the template does not exist
			display alert ¬
				"Template does not exist or
the document could not be created" buttons {"Cancel", "OK"} as warning
			-- If can't create document, then bail out of the whole shebang!
			quit application "Pages"
			return
		end try
		tell the front document
			--delete the default template text and make a new paragraph
			delete every paragraph
			make new paragraph at beginning
			tell body text
				-- put the selected text into the new paragraph
				set paragraph 1 to theSelection
			end tell
		end tell
		-- open the print dialog ready to print! Enclose in try block to ignore errors
		try
			print the front document with print dialog
		end try
	end tell
	return input
end run

Download All Links on a Web Page
There is a great add-on for “Firefox”:ff called “DownThemAll”:dta that lets you download all the links on a web page without the need to click on each link individually. I have not been able to find anything like it for Safari. I wanted to download several zip archives containing sample code for a tutorial I was working through and was certain this could be done using Automator. In just a few minutes I hacked together a workflow that finds links on the current Safari page, filters them by extension, and displays a list for me to select from, before downloading the links to the Downloads folder. This workflow makes use of several Safari specific actions.

Automator download all workflow

Copy or Move Files and Folders to iTunes
One of the easiest ways to add songs to iTunes is by copying audio files or folders containing songs to the aptly named Automatically Add to iTunes folder. While this is relatively easy, why not save a few mouse clicks and drags by adding a service to the contextual menu for Finder items like files and folders. Add one service to copy files or folders, and a second to move them.

Automator copy to iTunes workflow

I have services that copy and move files to my “Dropbox”:db folder, create tar archives from selected files and folders, and even automatically shorten a selected URL with “bit.ly”:bitly. Automator includes actions for working with text files, creating PDF documents, and even processing images. There is really no limit to the cool things you can do with Automator.

Resources
There are lots of great places online where you can find workflows. The best place to start is at “Mac OS X Automation”:osxautomation where you will not only find sample services, but some great tutorials about Automator and AppleScript.

Using Automator to build workflows is simple and takes little time to learn. Services are an effective way to automate repetitive tasks that save time. Make your computer work for you now by creating a few services of your own.

[automator]http://support.apple.com/kb/HT2488
[ff]http://mzl.la/dUTkIB
[dta]http://bit.ly/emqgQS
[db]http://db.tt/SVZWzX3
[bitly]http://bit.ly
[osxautomation]http://www.macosxautomation.com/services/download/index.html

Blogging from TextMate

I have _reluctantly_ been using “TextMate (TextMate)”:tm for a couple weeks. No text editor can ever take the place of “Vim”:vim, but there are several features that attracted me to “TextMate”:tm. So far I am impressed, and “TM”:tm makes editing HTML(HyperText Markup Language) and CSS(Cascading Style Sheets) a snap.

I will write about my experiences when time permits, but for now how about this… “blogging from”:blog “TextMate”:tm. That’s right, this post was written and posted from inside “TM”:tm!

[tm]http://macromates.com/
[vim (Vim)]http://www.vim.org/
[blog (Screencast: Blogging from TextMate)]http://screencasts.textmate.org/blogging_take_two.mov

5 Web Applications You Can’t Live Without

With ever-increasing amounts of information coming from every direction, and personal and professional lives that are busier than ever, it’s becoming more difficult to manage all the appointments, messages, notes, tasks, and details that are part of every day. If you need a little help, there are lots of well thought out web applications that provide solutions to many of life’s challenges.

Here’s five web applications you can’t live without: Continue reading “5 Web Applications You Can’t Live Without”

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)))

    else:
        pass

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

sys.exit(0)

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

[kde]http://www.kde.org/
[gnome]http://www.gnome.org/
[naut]http://www.gnome.org/projects/nautilus/
[vim]http://www.vim.org/

Another Serving

We just posted a “new episode (Mormon Potluck Podcast: Episode 4)”:episode of the “Mormon Potluck (Mormonpotluck.com)”:potluck podcast. This weekly podcast is created by 4 friends brought together by religion, and a love for all things tech. Each week we talk about life in general, how our “Mormon beliefs (Mormon.org)”:mormon affect our lives, news, politics, and the technologies we love (or hate).

[episode]http://www.mormonpotluck.com/2007/07/27/mormon-potluck-podcast-episode-4/
[potluck]http://www.mormonpotluck.com
[mormon]http://www.mormon.org

Mormon Potluck Podcast

If you haven’t had a chance to listen yet, you don’t know what you are missing! “Episode 2 (Mormon Potluck Podcast: Episode 2)”:episode of the “Mormon Potluck (Mormon Potluck)”:mormon Podcast is online now.

[mormon]http://www.mormonpotluck.com/
[episode]http://www.mormonpotluck.com/2007/06/29/mormon-potluck-podcast-episode-2/

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?

[maildir]http://en.wikipedia.org/wiki/Maildir
[brace]http://www.gnu.org/software/bash/manual/bashref.html#SEC27
[bash]http://www.gnu.org/software/bash/