Usul: non-POSIX tabular Unix utilities

Today I pushed usul to GitHub. Usul is a suite of non-POSIX replacements for the standard Unix command line utilities, designed to fix a number of problems POSIX enforces in the name of backwards compatibility. As an example, let’s take ls, which happens to be one of the very few utilities I’ve written so far. POSIX demands that the output of ls -Rl look something like this:

total 16
drwxr-xr-x  3 cls  cls   102  4 Jan  2012 colors
-rw-r--r--  1 cls  cls   261 28 Jun 23:04 gvimrc
-rw-r--r--  1 cls  cls  1104 28 Jun 23:10 vimrc

total 16
-rw-r--r--  1 cls  cls  7765  4 Jan  2012 molokai.vim

This is absolutely terrible if you want to do something with this information, like pipe it somewhere. We have these pointless “total 16” headers which we have to grep -v out of the way to begin with, then we have two different formats for timestamps depending on whether they’re older than six months or not, and… don’t even get me started on the “./colors:” format for recursing directories. Seriously. Now, Usul has output that is much more useful for piping around:

drwxr-xr-x  cls  cls  2012-01-04 14:36  colors/
-rw-r--r--  cls  cls  2012-01-04 14:36  colors/molokai.vim
-rw-r--r--  cls  cls  2012-06-28 23:04  gvimrc
-rw-r--r--  cls  cls  2012-06-28 23:10  vimrc

Each of those double spaces is actually a tab, which are field separators, and the line feeds are record separators, à la awk.

Well, it turns out that we have a totally separate utility called find, with an argument syntax totally unlike any other, largely for the reasons shown above. So we can use find to recursively list those directories, but if the paths contain a line feed we have to use find -print0 to separate files with NUL bytes instead of line feeds (which isn’t even in POSIX), and then we’ll need xargs -0 to read it again, but no other tools support that so we’ll probably end up creating some monstrous find query and the Unix philosophy is dead.

All Usul utilities use the environment variables FS and RS, field and record separators, just as awk does. find . -print0 is just the same as ls -R with FS= RS=, but all utilities (e.g., grep) would understand that the records are separated by NUL bytes, not just xargs. They are all ‘tabular’, so you don’t have to waste time coercing output from one program to another.

Another thing Usul does well is just having generally sane behaviour. ls -Rd will do what you expect, only ls -Ra will recurse into hidden directories, and so on. It’s also very pedantic about avoiding race conditions. Anyway, I’ll be quietly getting on with these. It’s mostly for my own benefit, but someone else might find them useful, too.