From mboxrd@z Thu Jan 1 00:00:00 1970 Message-Id: <200210312158.g9VLw1i06685@augusta.math.psu.edu> To: 9fans@cse.psu.edu Subject: Re: [9fans] find(1) revisited. In-Reply-To: Your message of "Thu, 31 Oct 2002 16:20:16 EST." <200210312120.g9VLKGi06485@augusta.math.psu.edu> From: Dan Cross Date: Thu, 31 Oct 2002 16:58:01 -0500 Topicbox-Message-UUID: 130360e2-eacb-11e9-9e20-41e7f4b1d025 Oh! I forgot to say how to use these. Sorry, my bad. Basically, compile walk and put it and sor in your bin directories. Walk takes ``-d n'' to limit the depth of the walk to the nth level in the target directory (walk -d 0 prints nothing), and ``-q'' to quote the output in the style of ls(1). These can of course be used in concert. For example, `walk -d 3 -q /dev' prints out everything up to 3 levels deep in /dev, quoting everything that needs to be. `walk -d 3 -q /dev /env' might be a better demonstration, as I think it's a rare thing indeed that something in /dev needs to be quoted. Sor works sort of like grep, except that you pass it tests. For instance, `walk -d 3 -q /dev /env | sor 'test -d' '' will print out the names of all the directories up to depth 3 in /dev and /env. Multiple tests can be put on the same line, effectively creating a logical `or' operator. For example, walk -d 3 -q /sys/lib | sor 'test -d' 'test -x' (interestingly, this shows /sys/lib/ghostscript/font/mkfile is executable on my system; how odd.) Of course, the usual combinations with grep, sed, etc, will work. A few Unix find idioms and their translations are: unix% find $home -name '*foo*' -print term% walk $home | grep foo unix% find $home -name '*foo*' -type d -print term% walk $home | grep foo | sor 'test -d' unix% find $home '(' -name '*foo*' -o -name '*bar*' ')' -type d -print term% walk $home | grep '(foo|bar)' | sor 'test -d' unix% find $home/* $home/*/* -prune '(' -name '*foo*' -o -name '*bar*' ')' -type d -print term% walk -d 2 $home | grep '(foo|bar)' | sor 'test -d' unix% find $home -name foo.c -exec ls '{}' ';' term% ls `{walk $home | grep '^foo.c$'} Incidentally, sor internally sets the environment variable ``file'' to the name of the current file being examined. This can be useful for some tests. For example: term% walk -d 1 | sor '/sys/lib/texmf/bin/386/newer $file' Which is basically a goofy way of printing the names of files in the current directory. Or the perhaps more useful: term% walk -d 1 | sor 'grep README $file > /dev/null' Which is a goofy way of doing: grep -l README `{walk -d 1} Anyway, further examples exist, but already the combination of walk and sor is just as expressive, but a lot shorter and simpler than find, et al. Also, it's easy to write other programs that perform tests similar to the rest of the find predicates (I have some simple scripts, for instance, that pull the size and owner/group of a file out of ls -l's output). - Dan C.