Wild card expansion
in Unix
This section used to be called “Linux
Recursive Grep: Insanity or Depravity”
or something like that, but then after the passing years, a
thoughtful correspondent wandered along and enlightened me. ... This
is the Unix recursive grep:
grep
-r - -include "*.h"
- -include "*.c"
lostfunction .
And it works very
nicely —
at least in my
Mandrake 8.2 Linux system here.... Please note
- Single hyphen
for
“-r”
- Double
hyphen for
“--include”.
- A single
concluding dot.
(I use this web site for my own
pointless Linux
investigations, and I was fooled.)
ZSH?
And then, after a million years, another country: apparently the “zsh”
shell has a kind of built-in recursion. The shell is available on many
linices — you just go “zsh” — but I then typed
in
“grep opendir **/*.h”
at /Developer/SDKs on my mini,
and got
an “argument list too long” error because, of course there
are
five
million .h files in those directories. ... So, close, but no cigar....
... But to start our sad story at the beginning:
grep is a
programmer’s command-line tool that searches for text within
files, and is essential for figuring-out where things are in
one’s enormous overgrown projects, i.e., here in MSDOS-land
(aka
Windows)
grep
-d lostfunction
*.c *.h
might spew-out the names and lines of c-language and
c-include
files
which include the text “lostfunction”. The
“-d”
option, at least in my Borland grep, means “-d Search
subdirectories” because, of course, most adults and some
children put our giant sprawling out-of-control projects in an entire
directory tree, and we’d like to search all
of it when
we’re trying to find something.
And for years, as I wandered the byways and back alleys
of
Unixism, I
was sure the hidden secrets of recursive grep would
be
revealed. ... I knew it wouldn’t
be easy; I actually found a Unixoid lecture some poor pilgrim how
yes, of course grep has recursion, read the manual
— but
the adept gave no example! ... I googled another
likely
suspect “examples/grep.pdf”, but apparently the
Unix police
got there first — the thing was gone 404 not present! ... I
encountered volunteers who were going to write their own recursive
greps someday, and cunning scripts that would make it work —
but
none of them knew of the magical
“--include” option....
... It was like when I encountered the MSDOS midnight
bug,
where the
time-of-day clock didn’t know about tomorrow if the computer
was
on at midnight, demonstrating, if there was any need, that the guys
at Microsoft were not the crazed lunatic all-night
hackers
they apparently wished to believe they were. ... Perhaps Unix, in its
secret heart, had no recursive grep! ... Oh the
shame! ...
But as it turned-out at last, it did,
as
my kindly
pilgrim
showed me. The option was there all the time! Let a thousand Linux
directories grep! ... Except — it was a
secret!
... Which brings us to ...
Unix’s Pathological
Inability to Communicate
I checked my many Linux manuals for grep, and it does
indeed
describe
the “--include” option:
--include
PATTERN
That’s it. I doubtless tried that a few times in the
years of
darkness, and of course it didn’t work. ... Now
I know, if
the documentation had been tortured with burning bamboo splints under
its fingernails it might’ve admitted that it really meant
--include
"QUOTED_PATTERN"
but I couldn’t
torture the Unix
documentation, as much as
I’ve yearned-to so many times....
Very Clever Shell
It works — or not — because of the exciting Unix
“shell” feature where AFNs
are
helpfully expanded, so if I type
“grep
lostfunction *.c *.h” on the Linux shell command-line, what
the
grep program gets to see is the vastly-improved “lostfunction
bingo.c
bongo.c dopo.c bingo.h dopo.h” — i.e., the shell
“expands” the asterisk (a well-known convention) to
show
all the files in the current directory that end
with
“.c” (for *.c) and “.h” (*.h).
... And quoting
wild-card expressions suppresses
expansion....
... In contrast, in the boringly-stupid
helplessly-primitive
MSDOS/Windows
world, nobody does that for you; shockingly, every program that wants
to provide this functionality has to do it itself. ... Like
Borland’s
grep.
Why is that?
MSDOS did it the dumb way because it’s dumb; it was
supposed
to
be a small harmless system for microcomputers, not
the mini
and giant Unix computers. ... By the time Linux rolled down the pike,
microcomputers were plenty powerful-enough to support such wonderful
shell features, but Microsoft didn’t bother, particularly
since
doing-so might break millions of existing batch files. ... Note that
both
MSDOS — and its even micro-er predecessor, CP/M, where I
first
encountered AFNs —
provide support
for
the feature with
functions that find one or more files based on an AFN, but the
program has to do much of the work.
So what?
The trick is, it’s harder to write
recursive grep (or
recursive anything) when the shell expands the AFNs — because
the shell necessarily expands them in the single current
directory
in which the program starts. ... Maybe Unix’s clever
shell
expansion wasn’t so clever, eh? They could’ve
instead
provided a callable expansion function to do a lot of the work (i.e.
as opposed to the primitive CP/M style); Windows probably has
one by now somewhere in the 5,000,000 APIs. Heck, Linux
has it — “glob”! ... So Unix could’ve done that
instead of
the shell expansion, and every single program would’ve had to
use those system calls — but only if they
needed AFN
expansion. The majority of programs don’t need
AFN
expansion, and they wouldn’t have to
“pay” for the
shell code they don’t use. ... So the design trade-off is not
really
that obvious, and perhaps the brilliant Unixoids did something wrong,
no? ...
... And then I finally bothered to look up Unix
“glob”, and
apparently
Long ago, in Unix V6, there was a program /etc/glob
that would expand
wildcard patterns. Soon afterwards this became a shell built-in.
... They don’t actually document
the glob
program,
naturally. ... So this was all deliberately
concocted, to make
the shell ever more powerful, intricate, and impossible to
understand! ... It’s something to do with the script/program
divide:
in Unix, creating executable programs is generally so appalling, and
script languages are so EZ and powerful, that providing AFN
expansion
for just programs wouldn’t fly — and forcing
scripts to use
glob or something for the purpose must’ve been intolerable.
In MSDOS and onwards (and before,
in CP/M!), we had the
inimitable Borland all-in-one
“Turbo” languages, which made creating executables
practically a no-brainer — versus the primitive MSDOS batch
files,
which may have stayed so primitive partly because
of
the inexpensive Turbo languages. ... And in a nicely complementary
fashion, *nix programming is so infuriating partly because
of
helpful features like wild-card expansion.
But Why Don’t Unix
Talk Good?
I am glad I have at last found a recursive grep. I can’t
really
complain that
grep
-r --include "*.h" --include "*.c"
lostfunction .
doesn’t run as trippingly off the fingers as
grep
-d lostfunction
*.c *.h
since for normal human beings, it all looks like insect
defecations.
... But I still figure we poor MSDOSers, suffering as we have for all
these years from inferiority complexes as the Unixers sneered at our
pitiful floppy-disk-based tripe, can still hold our heads up. ...
Our
operating system may be stupider than dirt, but because
of
this, it’s possible for normal mortals to get something done
in
it — as opposed to my years’ quest for Linux
recursive grep....
... It’s not that Microsoft is any
more
communicative than
the average Linux so-called manual; au contraire....
Nope.
It’s because MSDOS/Windows, at least at the command-line, is
incomparably simpler aka stupider.
(Both the Linux and
Windows GUIs are so infuriatingly opaque and annoying, it’s
hard to pick the loser.) The very fact that *nix has so many script
languages is a backward admission the shell procedure language is a
menace, and in fact many wise old *nixers solemnly warn
against programming in shell — without admitting or
apparently
even thinking that the problem might be runaway
shell
featureitis ... as in wild-card expansion....
Education
It doesn’t help that most Unixoids pick up their secret
hermetic
inner
knowledge during university education, but don’t
know that,
so, like so many stupid smart people, they imagine others’
ignorance of things that everybody knows (i.e.
everybody the
stupid smart person knows) is evidence of a simple childlike nature
in need of low-syllable-count instruction — when, instead, it
is
evidence of a different common psychological fault, the
absence of
psychic powers....
|