Path: utzoo!utgpu!cs.utexas.edu!usc!apple!amdcad!mozart.amd.com!diablo!monson From: monson@diablo.amd.com (Steve Monson) Newsgroups: alt.sources.d Subject: Re: Multiple executables in path (Was: NON-SOURCE POSTINGS CONSIDERED HARMFUL!) Message-ID: <1991Jan21.213907.26509@mozart.amd.com> Date: 21 Jan 91 21:39:07 GMT References: <1991Jan21.082717.22130@convex.com> <305:Jan2114:26:5191@kramden.acf.nyu.edu> <1991Jan21.171227.12138@convex.com> Sender: usenet@mozart.amd.com (Usenet News) Organization: Advanced Micro Devices, Inc., Austin, TX Lines: 171 In article <1991Jan21.171227.12138@convex.com> tchrist@convex.COM (Tom Christiansen) writes: >From the keyboard of brnstnd@kramden.acf.nyu.edu (Dan Bernstein): >:In article <1991Jan21.082717.22130@convex.com> tchrist@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 ) #!/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.