Hacker News new | comments | ask | show | jobs | submit login
Show HN: Notational `ls` - Never get lost in code again (hour long hack)
29 points by newhouseb on Sept 6, 2011 | hide | past | web | favorite | 16 comments
Hey folks, I just wanted to share a quick script I threw together called notational ls. One of the big problems of any code base (or any filesystem) is that it's hard to tell what's what - folder and file names often trade brevity for clarity.

So I thought about a version of `ls` that works like this:

  > nls
    web: Where python web server files are stored
    ad_hoc: One time scripts 
    ios: Our IOS code
Adding descriptions is really easy too:

  > nls images Images SHARED between both ios and web
    web: Where python web server files are stored
    ad_hoc: One time scripts 
    ios: Our IOS code
    images: Images SHARED between both ios and web
So I whipped up said script in python and pushed it to github for all to use. Code is at https://github.com/newhouseb/nls, feel free to fork as you so please, but I must get back to real work. If there's enough interest it'd be great to turn this into a larger effort of improving the small things in our bash lives. If you're lazy, here's the source anyway (github has comments and sane spacing) - enjoy!

  from subprocess import Popen, PIPE
  import sys
  files = Popen(["ls"], stdout=PIPE).communicate()[0].splitlines()
  notes = {}
      nls_file = open('.nls').read().splitlines()
  except IOError:
      nls_file = []
  for entry in nls_file:
      file, note = entry.split(':', 1)
      notes[file] = note
  if len(sys.argv) > 1:
      if len(sys.argv) == 2 and sys.argv[1] == 'bootstrap':
          for file in files:
              if file not in notes:
                  notes[file] = ''
      elif sys.argv[1] in files:
          notes[sys.argv[1]] = ' '.join(sys.argv[2:])
          '\n'.join([file+': '+note for file,note in notes.iteritems()]))
  for file in files:
      if file in notes:
          print '\033[1m' + file + ':\033[0m ' + notes[file].strip()
          print '\033[1m' + file + '\033[0m'
Note: I know this code isn't perfect, but it was a quick job and is what came to mind first and, most importantly, works. If you want to improve it send me a pull request/fork it on github (this is REALLY easy now with github's recent updates).

There's a lot of UNIX tools which are user-unfriendly, simply because they were designed not to be chatty. You can't use nls to pump a list of files into another script, which then uses the list of files to do something else useful. Chatty scripts can't be chained together.

Yet, controlling chatty output is something that is already done, with -v (verbosity) levels.

I wonder how much more usable UNIX would be, if -v was on by default, and there was some easy way to disable it when chaining tools.

Some distros do experiment with that, since it's relatively easy to ship some default aliases. For example, ls is often aliased to some combination of --color, -l, and -h.

Usually `-v` is used to increase verbosity in traditional unix applications (ls, mv, cp, etc). Or maybe I'm missing your point.

Corrected - "increase" -> "control".

My point is, UNIX tools are designed to be easy to use by the expert (easy to chain), but hard for beginners (not chatty).

There's also a lot of neglect towards giving users useful feedback, because feedback just doesn't happen by default, so why improve it?

`Popen(["ls"], ...)`? Was `os.listdir` (or, if you must, `sorted(fn for fn in os.listdir('.') if not fn.startswith('.'))` too easy?

An interesting solution would be using xattrs to store descriptions. Freedesktop.org has proposed[1] user.xdg.comment attribute, maybe it could be used.

[1] http://www.freedesktop.org/wiki/CommonExtendedAttributes#lin...

Clickable github link:


Better yet would be to use extended file attributes to store the description with the file itself. See attr(5)/getfattr(1)/setfattr(1). Unfortunately I don't think extended attributes are preserved by most version control systems :/

A find analogue would be a cool extension of this idea: it'd be cross-language tool that shows you the definition of a given function, or where a function is used, or otherwise lets you run simple queries on your code base.

    cat .nls


Just for kicks, here's a (terribly ugly) pipeline that will display the contents of .nls and `ls`, with duplicates removed:

ls | cat .nls - | column -t -s: | sort -r | perl -ane 'print unless $x{$F[0]}++'

and then obviously just echo "dirname: description" >> .nls to append to the file.

I would be interested in seeing a better pipeline, one that doesn't need perl/awk/ruby/what have you to remove the duplicates correctly.

The join(1) command is designed to do exactly this:

join -a2 -t: <(sort .nls) <(ls | sort)

(I think this is different from your pipeline, in that your pipeline will print files in .nls that aren't actually in the directory.)


Oh hey, this is awesome! I thought about doing something like this but then opted for the (ultimately more flexible) python script.

Is fine too, but you wont get non-annotated files. nls was designed to work within your normal workflow, i.e. doesn't require you to think about getting file notes in order to get them.

Interesting utility. Just tried it. Thanks.

Applications are open for YC Summer 2019

Guidelines | FAQ | Support | API | Security | Lists | Bookmarklet | Legal | Apply to YC | Contact