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

Steve Monson monson at diablo.amd.com
Tue Jan 22 08:39:07 AEST 1991


In article <1991Jan21.171227.12138 at convex.com> tchrist at convex.COM (Tom Christiansen) writes:
>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>)

#!/bin/csh

#As a matter of fact, you can do in csh just what you did in perl. I'm not
#a csh fanatic, but I remember how much I liked it over the Bourne shell,
#with its aliases and history, etc. In this example:

set file=$1
foreach dir ($path)
  if ( -x $dir/$file ) echo $dir/$file
end

#or, to add multiple arguments on the command line:

foreach arg ($argv)
  set file=$arg
  foreach dir ($path)
    if ( -x $dir/$file ) echo $dir/$file
  end
end

#The offending one-liner is a bit obscure, I admit, but then one-line mania
#is usually prone to generation of convoluted expressions. The nice thing
#about sh, ksh, perl is that the loops can be put on a single line if you
#want, but csh makes you split it up into multiple lines, making an alias
#impossible.

# But even with a one-liner, it's not as bad as that horribly convoluted
# example that was posted:

ls -1 {`echo $PATH|tr ':' ','`}/$1 |& grep -v 'not found'

# or, with multiple arguments:

foreach arg ($argv)
  ls -1 {`echo $PATH|tr : ,`}/$arg |& grep -v 'not found'
end
It's not whether you win or lose

It's whether *I* win or lose.



More information about the Alt.sources.d mailing list