Multiple executables in path (Was: NON-SOURCE POSTINGS CONSIDERED HARMFUL!)

Tom Christiansen tchrist at convex.COM
Tue Jan 22 04:12:27 AEST 1991


>From the keyboard of brnstnd at kramden.acf.nyu.edu (Dan Bernstein):
:In article <1991Jan21.082717.22130 at convex.com> tchrist at convex.COM (Tom Christiansen) writes:
:> The quotes you needed for your solution were gross and nigh
:> unto illegible.
:
:Illegible? It's not my fault if you haven't written enough shell code to
:instantly recognize '\''. Or would you prefer double quoting?

There's our Dan, who when he cannot win his point on technical merits,
resorts instead to petty, unfounded (and flat-out wrong), ad hominem
attacks laced with deprecating sarcasm in order to belittle the other
party.  Why does it make you feel better to insult other people, Dan?  Is
it because you think so little of yourself you have to put everybody else
down?  If that's your game, why don't you go off to Fidonet or some other
even more puerile bulletin board system where this behavior may be more
expected?  Better yet, go see a good counselor.  Maybe you wouldn't be
posting so much drivel if you hadn't been kicked out of Princeton.  Would
you care to tell us all about that incident, Dan?  And while you're at it,
it would be interesting to learn what is wrong inside of you that makes
you want to convert every newsgroup you touch into a battleground for
petulant, anal-retentive abuse?  What ever did happen to rec.games.rpg
anyway?

:  echo `echo "$PATH" | tr : '\012' | sed -e 's+$+/!:1+' -e 's:^:/.[.]:'`
:    | sed 's:/../:/:g'

:It's just not as instantly obvious as the pipeline. I prefer easily
:maintainable code with obvious data flaw (and obvious firewalls) to an
:unportable, unconventional, ungodly muck.

Data flaw?  There you have it.

Unportable: I think not.  In fact, perl runs on more machines than 
sed and tr.  I've not seen DOS or Macintosh ports of them, let alone
of the shell-from-hell you like to post things in.

Unconventional:  That's what the Fortran programmer said when he
first saw Algol, Pascal, C, etc.  Or if you prefer, the MVS hack
when he saw UNIX.  As you can seen, this argument merely demonstrates
a myopic approach to new and better technology.

Ungodly:  Oh, now *there's* an effective criticism for you.  I'm sure
the whole net will rise up in popular accord for this one.  With gods
on your side, who can stand against you?  

Anything that requires multiple levels of evaluation is more complex than
something that does not.  You are looking at the problem from a "munge the
I/O stream until done" approach, which is often just a crufty hack for
inadequate tools.

Let's sit back and look at the algorithm.  What is really desired here?
It's really much simpler than you've made it out to be.  All that's
needed is to check each component in the user's path for an executable
of that name, and if it exists, print out the full pathname.  That's
surely not an algorithm that's conveyed by your solution, but that's 
all that's needed here.

Here's my solution:

    $file = shift;
    for $dir (split(/:/,$ENV{"PATH"})) {
	print "$path\n" if -x ($path="$dir/$file");
    }

I've not gone to much trouble to obfuscate it, like using && notation:

	-x ($path="$dir/$file") && print "$path\n";

or some greply convolution.

If you want it unraveled a bit because you prefer assignments to stand on
their own and not be used in expressions, you could have this:

    $file = shift;
    for $dir (split(/:/,$ENV{"PATH"})) {
	$path = "$dir/$file";
	if (-x $path) {
	    print "$path\n";
	}
    }

Notice how easily I can deal with multiple arguments by simply slapping
another for loop around everything:

    for $file (@ARGV) {
	for $dir (split(/:/,$ENV{"PATH"})) {
	    print "$path\n" if -x ($path="$dir/$file");
	}
    }

Notice how little confusion is added by adding that functionality.
That's not easily done in csh.  

I'd like to see others' opinions on algorithmic complexity here.  Which 
way is more straightforward?  Bear in mind that Dan's solution, here
reproduced for your inspection:

    alias which 'echo `echo "$PATH" | tr : '\''\012'\'' | sed -e '\''s+$+/\!:1+'\'' -e '\''s:^:/.[.]:'\''` | sed '\''s:/../:/:g'\'''

contains 30 quotes, 9 backslashes, and several levels of evaluation to
worry about.  Of course, in a real shell instead of the abomination cited
above, most of these problems go away:

    function mwhence {
	for file in $*; do
	    for dir in `echo $PATH | tr ':' ' '`; do
		path=$dir/$file
		if [ -x $path ]; then echo $path; fi
		# AKA: test -x $path && echo $path
	    done
	done
    }

For the truly curious, the ksh solution takes 2x time time the perl one
does, probably because of having to call tr.  If I had used the ## or %%
variable munging, I probably could have trimmed this down, but that's not
as succinctly expressed and I didn't feel like playing with it.  It's a
good deal faster than the disgusting csh alias.

We'll see who has to say what here about the shell and the perl algorithm
(which are equivalent) versus the massively piped one.  Of course, a lot
of the UNIX gurus are here in Dallas right now for USENIX, plus a lot more
have given up on the alt hierarchy, and a few have given up on anything
that should really have been posted to alt.flame.dan-bernstein instead.

--tom
--
"Hey, did you hear Stallman has replaced /vmunix with /vmunix.el?  Now
 he can finally have the whole O/S built-in to his editor like he
 always wanted!" --me (Tom Christiansen <tchrist at convex.com>)



More information about the Alt.sources.d mailing list