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