mleisher@nmsu.edu (Mark Leisher) (01/19/91)
Tom's Perl script reminded me of a program I have that hasn't been posted for a while. Here's a program called which5 by Maarten Litmaath that is particularly fast at finding executables that occur more than once in a path. ---- Cut Here and feed the following to sh ---- #!/bin/sh # This is a shell archive (produced by shar 3.49) # To extract the files from this archive, save it to a file, remove # everything above the "!/bin/sh" line above, and type "sh file_name". # # made 01/18/1991 23:55 UTC by mleisher@nmsu.edu # Source directory /thrinakia1/mleisher/c_stuff # # existing files will NOT be overwritten unless -c is specified # # This shar contains: # length mode name # ------ ---------- ------------------------------------------ # 169 -rw-rw-r-- which5/Makefile # 2384 -rw-rw-r-- which5/which.1 # 5142 -rw-rw-r-- which5/which5.c # # ============= which5/Makefile ============== if test ! -d 'which5'; then echo 'x - creating directory which5' mkdir 'which5' fi if test -f 'which5/Makefile' -a X"$1" != X"-c"; then echo 'x - skipping which5/Makefile (File already exists)' else echo 'x - extracting which5/Makefile (Text)' sed 's/^X//' << 'SHAR_EOF' > 'which5/Makefile' && # Makefile for /usr/local/bin/which X which: which5.c X cc -O which5.c -o which X install: which X /bin/mv -f which /usr/local/bin X doc: X nroff -man which.1 > which.man SHAR_EOF chmod 0664 which5/Makefile || echo 'restore of which5/Makefile failed' Wc_c="`wc -c < 'which5/Makefile'`" test 169 -eq "$Wc_c" || echo 'which5/Makefile: original size 169, current size' "$Wc_c" fi # ============= which5/which.1 ============== if test -f 'which5/which.1' -a X"$1" != X"-c"; then echo 'x - skipping which5/which.1 (File already exists)' else echo 'x - extracting which5/which.1 (Text)' sed 's/^X//' << 'SHAR_EOF' > 'which5/which.1' && .TH WHICH 1 Apr\ 04\ 1990 .SH NAME which \- give alias, function or path expansion of command .SH SYNOPSIS .B which [ .B \-i ] [ .B \-a ] [ .B \-\- ] [ .I command ] .SH DESCRIPTION .I Which provides the user with the full expansion of the .I command argument, be it either an \fIalias\fR, a \fIshell function\fR or an executable file (default). To enable search for .I aliases and \fIshell functions\fR the user should supply the `\fI\-i\fR' (= interactive) flag. In that case .I which expects as standard input the expansion of the \fIalias\fR or \fIshell function\fR. If the standard input is empty or the `\fI\-i\fR' flag has not been given, \fIwhich\fR will try to locate \fIcommand\fR in the user's \fBPATH\fR. The interactive mode is easily used by setting an .I alias like the following: .ft B .nf X X alias which alias !\\$ \\| /usr/local/bin/which \-i !\\* X .fi .ft R in \fIcsh\fR, or .ft B .nf X X alias which eval alias '\\"\\$$#\\" |' \\ X /usr/local/bin/which \-i '${1+"$@"}' X .fi .ft R in shells which are supersets of .I sh and which know \fIaliases\fR. If your shell has \fIshell functions\fR, you can use the following function: .ft B .nf X X which() X { X eval last=\\"\\$$#\\" X set | sed \-n "/^$last(){$/,/^}$/p" | X /usr/local/bin/which \-i ${1+"$@"} X } X .fi .ft R If the `\fI\-a\fR' (= all) flag is given, .I which will not stop after the first `match', but search for all occurrences of .I command in the user's .B PATH. The `\fI\-\-\fR' flag can be used to end the list of options: the next argument (if present) will be taken as \fIcommand\fR, even if it starts with a `\-'. \fIWhich [\-i] [\-a] [\-\-]\fR without further arguments prints the user's .B PATH broken up into its components, one per line. .PP This new version of the .I which command is not a .I csh script. Being an executable it is much faster, and not sourcing .I .cshrc it gives a true picture of one's .I aliases. Furthermore it will give the correct answers even if: .IP \- the \fIeffective uid\fR (\fIgid\fR) differs from the \fIreal\fR uid (gid) .IP \- the effective uid is 0 (\fIroot\fR). .SH EXAMPLE .ft B .nf % alias which alias !$ | /usr/local/bin/which \-i !* % which which which alias !$ | /usr/local/bin/which \-i !* % which \-a which which alias !$ | /usr/local/bin/which \-i !* /usr/local/bin/which /usr/ucb/which % .fi .ft R .SH AUTHOR Maarten Litmaath @ VU Informatika Amsterdam SHAR_EOF chmod 0664 which5/which.1 || echo 'restore of which5/which.1 failed' Wc_c="`wc -c < 'which5/which.1'`" test 2384 -eq "$Wc_c" || echo 'which5/which.1: original size 2384, current size' "$Wc_c" fi # ============= which5/which5.c ============== if test -f 'which5/which5.c' -a X"$1" != X"-c"; then echo 'x - skipping which5/which5.c (File already exists)' else echo 'x - extracting which5/which5.c (Text)' sed 's/^X//' << 'SHAR_EOF' > 'which5/which5.c' && /* X * which [-i] [-a] [--] [<command>] X * alias which alias !\$ \| /usr/local/bin/which -i !\* X * alias which 'eval alias \$$# | /usr/local/bin/which -i ${1+"$@"}' X * which() X * { X * eval last=\"\$$#\" X * set | sed -n "/^$last(){$/,/^}$/p" | X * /usr/local/bin/which -i ${1+"$@"} X * } X * X * Author: Maarten Litmaath @ VU University Amsterdam (maart@cs.vu.nl) X * First change: X * Emile LeBlanc (leblanc%math.Berkeley.EDU@ucbvax.berkeley.edu) notes X * the access() system call considering everything executable for X * root (!), so we give root a special treatment. :-( X * `which', `which -i' and `which -a' with no further arguments now X * return the PATH environment variable, split up into its components. X * The aliases defined above are slightly different from the previous X * version - now it's the shell who's doing the alias checking. X * Second change: X * Added support for shell functions and multiline aliases, added the X * `--' option, changed the source style. X * Third change: X * To hell with access()! X * Now stat() is used to give the right answer even if the effective X * uid (gid) differs from the real uid (gid). X * We can't use setuid(geteuid()), because that's nonportable. :-( X * Fourth change: X * Jim Meyering <meyering@cs.utexas.edu> notes convert() will clobber X * the stack if the PATH is longer than BUF_SIZE - 1 characters. X * I've changed convert() altogether to return a path vector (cf. argv), X * whose components are the respective directories in the PATH. X * Furthermore in printing the PATH there are no trailing colons anymore. X */ X #include <sys/types.h> #include <sys/stat.h> #include <stdio.h> X #define BUF_SIZE 512 #define M_USR 0700 #define M_GRP 0070 #define M_OTH 0007 #define X_ALL 0111 #define R_ALL 0444 X char Version[] = X "@(#)which 5.0 90/03/24 Maarten Litmaath @ VU Informatika Amsterdam"; char *Prog; X X void usage() { X fprintf(stderr, "Usage: %s [-i] [-a] [--] [<command>]\n", Prog); X exit(1); } X X main(argc, argv) int argc; register char **argv; { X register char *path, *s, **pathv, **p; X char *strcpy(), *getenv(), *fgets(), buf[BUF_SIZE], **convert(); X int all = 0, inter = 0, stop = 0, found = 0, uid, gid, mask, X xmask, rmask; X struct stat st; X void usage(); X X X Prog = *argv++; X --argc; X X while (!stop && (s = *argv) && (*s == '-')) { X ++argv; X --argc; X ++s; X while (*s) X switch (*s++) { X case 'a': X all = 1; X break; X case 'i': X inter = 1; X break; X case '-': X stop = 1; X break; X default: X usage(); X } X } X X if (argc > 1) X usage(); X X if (inter && *argv) { X while (fgets(buf, sizeof buf, stdin)) { X if (!found) { X printf("%s", *argv); X found = 1; X } X printf("\t%s", buf); X } X if (found && !all) X exit(0); X } X X if (!(path = getenv("PATH"))) { X fprintf(stderr, "%s: no PATH in environment!\n", Prog); X exit(1); X } X X if (!*path) X path = "."; /* another dubious convention */ X X pathv = convert(path); /* convert path string to vector */ X X if (!*argv) { /* print path if no more arguments */ X while (*pathv) X puts(*pathv++); X exit(0); X } X X uid = geteuid(); X gid = getegid(); X if (uid == 0) { X xmask = X_ALL; X rmask = R_ALL; X } X X for (p = pathv; path = *p++; ) { /* try every component */ X s = buf; X while (*s++ = *path++) X ; X (void) strcpy(s, *argv); X *--s = '/'; X X if (stat(buf, &st) != 0 || (st.st_mode & S_IFMT) != S_IFREG) X continue; X X /* file exists and is regular */ X X if (uid != 0) { X mask = st.st_uid == uid ? M_USR : X st.st_gid == gid ? M_GRP : M_OTH; X xmask = X_ALL & mask; X rmask = R_ALL & mask; X } X X if (!(st.st_mode & xmask)) X continue; X X /* file is executable */ X X *s = 0; X if (stat(buf, &st) != 0) { X perror(buf); X continue; X } X X if (!(st.st_mode & rmask)) { X fprintf(stderr, X "%s: %s found in unreadable directory %s!\n", X Prog, *argv, buf); X found = 1; X continue; X } X X /* directory is readable */ X X *s = '/'; X puts(buf); X if (!all) X exit(0); X found = 1; X } X X if (found) X exit(0); X X fprintf(stderr, "%s not found in:\n", *argv); X while (*pathv) X fprintf(stderr, "%s\n", *pathv++); X exit(1); } X X char **convert(path) char *path; { X register char *s, c; X register int pathc; /* the length of the path vector */ X char **v, **pathv, *malloc(); X X for (s = path, pathc = 2; c = *s++; ) X if (c == ':') X ++pathc; X X if (!(pathv = (char **) malloc(pathc * sizeof(char *)))) { X perror("malloc"); X exit(1); X } X X for (s = path, v = pathv; (c = *s) != '\0'; ) { X if (c == ':') { X /* X * This colon is spurious. According to some X * dubious convention it is made equivalent to a dot. X */ X *v++ = "."; X if (*++s == '\0') X *v++ = "."; X /* X * The PATH ended in a spurious colon. X * To be consistent we add another dot X * to the path vector. One day you'll X * be glad we did. X */ X } else { X *v++ = s; X while ((c = *++s) != '\0') X if (c == ':') { X *s++ = '\0'; X if (*s == '\0') X *v++ = "."; X /* X * The PATH ended in a X * (spurious) colon, so X * add dot to the vector. X */ X break; X } X } X } X X *v = 0; /* Signal the end of the path vector. */ X X return pathv; } SHAR_EOF chmod 0664 which5/which5.c || echo 'restore of which5/which5.c failed' Wc_c="`wc -c < 'which5/which5.c'`" test 5142 -eq "$Wc_c" || echo 'which5/which5.c: original size 5142, current size' "$Wc_c" fi exit 0 ----------------------------------------------------------------------------- mleisher@nmsu.edu "I laughed. Mark Leisher I cried. Computing Research Lab I fell down. New Mexico State University It changed my life." Las Cruces, NM - Rich [Cowboy Feng's Space Bar and Grille]
brnstnd@kramden.acf.nyu.edu (Dan Bernstein) (01/19/91)
Hmmm. I've always been satisfied with the speed of alias which 'echo `echo "$PATH" | tr : '\''\012'\'' | sed -e '\''s+$+/\!:1+'\'' -e '\''s:^:/.[.]:'\''` | sed '\''s:/../:/:g'\''' ---Dan
tchrist@convex.COM (Tom Christiansen) (01/19/91)
From the keyboard of brnstnd@kramden.acf.nyu.edu (Dan Bernstein): :Hmmm. I've always been satisfied with the speed of : : alias which 'echo `echo "$PATH" | tr : '\''\012'\'' | sed -e '\''s+$+/\!:1+'\'' -e '\''s:^:/.[.]:'\''` | sed '\''s:/../:/:g'\''' But it doesn't do the same thing as mine does, Dan. Yours is more like this: for $file (@ARGV) { for $dir (split(/:/,$ENV{'PATH'})) { print $path,"\n" if -x ($path="$dir/$file"); } } except that it uses many more processes, runs more slowly, and is significantly more difficult to read and thus maintain. But as I said, the original code does something different: it doesn't just tell you which paths lead to a particular command. Rather, it produces a complete list of all commands in your $PATH with more than one path to them, except for those duplicates that are just there due to symlinks to the same executable and by the same name, such as /etc/foo -> /usr/etc/foo. That's why the $files{$name, $dev, $ino} array is kept. I doubt you can do the last part with a csh alias, and even if you could, I wouldn't want to try to make sense out of it, unless of course it just pointed to my script. :-) --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@convex.com>)
tchrist@convex.COM (Tom Christiansen) (01/19/91)
Oops -- read the postings out of order, and somehow thought Dan was replying to me. I kinda like Maarten's version in that it catches aliases. --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@convex.com>)
brnstnd@kramden.acf.nyu.edu (Dan Bernstein) (01/21/91)
In article <1991Jan19.105624.15369@convex.com> tchrist@convex.COM (Tom Christiansen) writes: > From the keyboard of brnstnd@kramden.acf.nyu.edu (Dan Bernstein): > :Hmmm. I've always been satisfied with the speed of > : alias which 'echo `echo "$PATH" | tr : '\''\012'\'' | sed -e '\''s+$+/\!:1+'\'' -e '\''s:^:/.[.]:'\''` | sed '\''s:/../:/:g'\''' > But it doesn't do the same thing as mine does, Dan. I didn't say that it did. Yours produces a result that is useful in only a limited problem domain, and I don't see why I should write a 35-line script for a useless result. > Yours is more like this: > for $file (@ARGV) { > for $dir (split(/:/,$ENV{'PATH'})) { > print $path,"\n" if -x ($path="$dir/$file"); > } > } > except that it uses many more processes, runs more slowly, I tried the Perl version and the csh version on two different machines. The csh version uses three execs and four processes, but because tr and sed are one tenth the size of perl, the perl version is *SLOWER*. > and is > significantly more difficult to read and thus maintain. Oh? I see ``echo path, colons to newlines, tack argument on end of line and /.[.] on beginning, glob, trash that beginning ..,'' which makes perfect sense. The Perl version has all these confusing parenthesization and quoting conventions, as well as -x. What's -x? Izzat from test? What's worse, there's no obvious linear flow through the Perl code; ``file'', for example, appears near the beginning and near the end, and your eyes have to jump all around to trace the data flow. So the Perl version is slower, takes more memory, and is more difficult to read and thus maintain. Sounds like a loser to me. > But as I said, the original code does something different: it doesn't just > tell you which paths lead to a particular command. Rather, it produces a > complete list of all commands in your $PATH with more than one path to > them, Yay. > except for those duplicates that are just there due to symlinks to > the same executable and by the same name, such as /etc/foo -> > /usr/etc/foo. That's why the $files{$name, $dev, $ino} array is kept. I > doubt you can do the last part with a csh alias, Rather than expressing your doubt, why don't you spend thirty seconds putting together the right combination of ls, rev, and sort to eliminate your doubt? ---Dan
tchrist@convex.COM (Tom Christiansen) (01/21/91)
Go away, Dan. The quotes you needed for your solution were gross and nigh unto illegible. If you can't follow a simple three-line piece of simple flow-control, I'm sorry for you. The quoting is also obvious -- go read your shell man page about $foo interpolation in double-quoted strings. The parens make sense if you spend 5 seconds looking at them, thinking about lists in csh, function calls (split) and the precedence of assignment statements. Following the principle of least surprise, -x is obviously from /bin/test. My solution really is much faster on my machine, and provably so. Some people want to bend over backwards for slow, convoluted solutions that you have to dick with to get just quite right; others don't. You do what you want, I'll do what I want, and so will everybody else; they'll decide what's better and easier for them. --tom MINE: for $file (@ARGV) { for $dir (split(/:/,$ENV{"PATH"})) { print "$path\n" if -x ($path="$dir/$file"); } } DAN'S: alias which 'echo `echo "$PATH" | tr : '\''\012'\'' | sed -e '\''s+$+/\!:1+'\'' -e '\''s:^:/.[.]:'\''` | sed '\''s:/../:/:g'\''' -- "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@convex.com>)
brnstnd@kramden.acf.nyu.edu (Dan Bernstein) (01/21/91)
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? Has it ever occurred to you that if there were a usable Perl shell, then it would require just as much special quoting as csh aliases do? I could put the alias into a separate file so that we're on even ground. Still, if you don't want to figure out the quoting conventions, you can just feed csh the alias and type ``alias which'' to see the unquoted version: echo `echo "$PATH" | tr : '\012' | sed -e 's+$+/!:1+' -e 's:^:/.[.]:'` | sed 's:/../:/:g' C'mon, surely you admit that ``echo path, make colons into newlines, add argument at end, add /.[.] at beginning, glob, trash /..'' is not only an exact reading of the command in linear order, but a perfectly sensible solution. Again, your Perl solution has no obvious linear flow, and your eyes have to keep jumping around to see where the data goes. (If you want to put quotes back into an alias, use the ``quote'' and ``makealias'' aliases, which have been running around for quite some time now. It takes soooo much effort.) > If you can't follow a simple three-line piece of simple > flow-control, I'm sorry for you. 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. > The quoting is also obvious -- go read > your shell man page about $foo interpolation in double-quoted strings. Right, so $path="$dir/$file" means to find the value of path, interpret that as the name of an environment variable, and set that to $dir/$file. 'Zactly like the shell. > The parens make sense if you spend 5 seconds looking at them, Yeah. That's about 5 seconds too much. > My solution really is much faster on my > machine, and provably so. Yes, your Convex probably has perl running all the time, so it doesn't have to be loaded from disk. The large address space must help too. > Some people want to bend over backwards for > slow, convoluted solutions that you have to dick with to get just quite > right; Yeah. Like yours. ---Dan
tchrist@convex.COM (Tom Christiansen) (01/22/91)
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 <tchrist@convex.com>)
monson@diablo.amd.com (Steve Monson) (01/22/91)
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 <tchrist@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.
maart@cs.vu.nl (Maarten Litmaath) (01/22/91)
In article <17373:Jan1908:30:3191@kramden.acf.nyu.edu>, brnstnd@kramden.acf.nyu.edu (Dan Bernstein) writes: )Hmmm. I've always been satisfied with the speed of [_Excessively_ long line split.] ) alias which 'echo `echo "$PATH" | tr : '\''\012'\'\ ) ' | sed -e '\''s+$+/\!:1+'\'' -e '\''s:^:/.[.]:'\'\ ) '` | sed '\''s:/../:/:g'\''' This alias doesn't deal with aliases (easily fixed), but most importantly it _fails_. Two examples: % which passwd /bin/passwd /usr/bin/passwd /etc/passwd # How odd: /etc/passwd is executable! % set path=($path .) % cp /bin/true foo % which foo # Silence. Had you read the documentation of `which5', you would have known it's not that trivial to get things right. -- kinnersley@kuhub.cc.ukans.edu (Bill Kinnersley): "Do phonograph turntables turn the other way in Australia?" gjh@krebs.acc.Virginia.EDU (Galen J. Hekhuis) "How do you think satanic messages were discovered on records?"
kaul@icarus.eng.ohio-state.edu (Rich Kaul) (01/22/91)
In article <1991Jan21.171227.12138@convex.com> tchrist@convex.COM (Tom Christiansen) writes: Here's my solution: $file = shift; for $dir (split(/:/,$ENV{"PATH"})) { print "$path\n" if -x ($path="$dir/$file"); } [ ... ] I'd like to see others' opinions on algorithmic complexity here. Which way is more straightforward? After seeing Dan's solution, either the perl code or the ksh script are far simpler to maintain for most users. I would hate to give that alias to some naive user. The first time he looked at his list of aliases and wanted an explaination of what that alias did would take a lot of educating in slightly more obsure things than most users need to know -- and it's more time that I have to spend on such things. Besides, I have a soft spot for perl ;-) Also, I should mention that none of the the above solutions work well with bash, where you can have a PATH with unexpanded ~ references in the PATH environment variable. There are other tricks you have to play on that shell to get these scripts to work. -- Rich Kaul | Every man is given the key to the door kaul@icarus.eng.ohio-state.edu | of heaven; unfortunately, the same key or ...!osu-cis!kaul | opens the door to hell.
tchrist@convex.COM (Tom Christiansen) (01/22/91)
From the keyboard of kaul@icarus.eng.ohio-state.edu (Rich Kaul): :Also, I should mention that none of the the above solutions work well :with bash, where you can have a PATH with unexpanded ~ references in :the PATH environment variable. There are other tricks you have to :play on that shell to get these scripts to work. That's odd -- if you have unexpanded tildes in your environment, I wonder how you get system, popen, and execlp to work without changing the C library. --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@convex.com>)
pfalstad@phoenix.Princeton.EDU (Paul Falstad) (01/22/91)
tchrist@convex.COM (Tom Christiansen) wrote: >From the keyboard of kaul@icarus.eng.ohio-state.edu (Rich Kaul): >:with bash, where you can have a PATH with unexpanded ~ references in >That's odd -- if you have unexpanded tildes in your environment, >I wonder how you get system, popen, and execlp to work without >changing the C library. You don't, it seems. At least it didn't work for me. This is probably a bug in bash. You should use $HOME instead of ~ when you define your PATH. -- Paul Falstad, pfalstad@phoenix.princeton.edu PLink:HYPNOS GEnie:P.FALSTAD In the heat of composition I find that I have inadvertently allowed myself to assume the form of a large centipede. I am accordingly dictating the rest to my secretary.
kaul@icarus.eng.ohio-state.edu (Rich Kaul) (01/23/91)
In article <5570@idunno.Princeton.EDU> pfalstad@phoenix.Princeton.EDU (Paul Falstad) writes: tchrist@convex.COM (Tom Christiansen) wrote: >From the keyboard of kaul@icarus.eng.ohio-state.edu (Rich Kaul): >:with bash, where you can have a PATH with unexpanded ~ references in >That's odd -- if you have unexpanded tildes in your environment, >I wonder how you get system, popen, and execlp to work without >changing the C library. You don't, it seems. At least it didn't work for me. This is probably a bug in bash. You should use $HOME instead of ~ when you define your PATH. Hmmm, I beg to disagree. Also, $HOME is not appropriate when searching another user's directory, cf: Script started on Tue Jan 22 08:45:16 1991 bash$ echo $PATH /usr/1/kaul/bin:/usr/1/kaul/bin/sun3:/usr/bin/X11:/usr/local/gnu/bin:/usr/local/bin:~octtools/bin:~cad/bin:/usr/ucb:/usr/bin:/usr/etc:. bash$ which magic /usr/1/cad/bin/magic bash$ magic Magic - Version 6.3 - Last updated Thu Sep 13 13:21:25 PDT 1990 Using technology "scmos". > :quit bash$ exit exit script done on Tue Jan 22 08:46:09 1991 (saying ~cad/bin/magic gives the same result). Bash does the expansion of the ~ before running the program. It is possible to force the expansions manually, but that's usually more work than desired. Besides, the ~ in bash has more functions than the equivalent ~ in csh (see Chet Ramey's bash man page for more information). Obligatory plug for bash: it's worth it. It's a very nice shell, with full emacs editing and very good vi editing if that's your dialect. It's certainly more fun than tcsh, which I used before, and has a more POSIX-ified behavior. There are still some bugs, although Chet's version is nearly bug free, and version 1.06 is long overdue. I liked it so much, I use the shell (or something to that effect). -- Rich Kaul | Every man is given the key to the door kaul@icarus.eng.ohio-state.edu | of heaven; unfortunately, the same key or ...!osu-cis!kaul | opens the door to hell.
chet@odin.INS.CWRU.Edu (Chet Ramey) (01/23/91)
In article <5570@idunno.Princeton.EDU> pfalstad@phoenix.Princeton.EDU (Paul Falstad) writes: >tchrist@convex.COM (Tom Christiansen) wrote: >>From the keyboard of kaul@icarus.eng.ohio-state.edu (Rich Kaul): >>:with bash, where you can have a PATH with unexpanded ~ references in >>That's odd -- if you have unexpanded tildes in your environment, >>I wonder how you get system, popen, and execlp to work without >>changing the C library. > >You don't, it seems. At least it didn't work for me. This is probably >a bug in bash. You should use $HOME instead of ~ when you define >your PATH. It's not a bug in bash. It's bash doing something useful with what would otherwise be useless. You have to go through special pains to get an unexpanded tilde in your PATH, since tilde expansion is performed on the rhs of assignment statements. The only way you can get a tilde into your path is to surround it with quotes. It might be a bug that double quotes can inhibit the expansion. Chet -- Chet Ramey ``There's just no surf in Network Services Group Cleveland, U.S.A. ...'' Case Western Reserve University chet@ins.CWRU.Edu My opinions are just those, and mine alone.
pfalstad@phoenix.Princeton.EDU (Paul Falstad) (01/23/91)
kaul@icarus.eng.ohio-state.edu (Rich Kaul) wrote: >In article <5570@idunno.Princeton.EDU> pfalstad@phoenix.Princeton.EDU (Paul Falstad) writes: > tchrist@convex.COM (Tom Christiansen) wrote: > >From the keyboard of kaul@icarus.eng.ohio-state.edu (Rich Kaul): > >That's odd -- if you have unexpanded tildes in your environment, > >I wonder how you get system, popen, and execlp to work without > >changing the C library. > You don't, it seems. At least it didn't work for me. This is probably > a bug in bash. You should use $HOME instead of ~ when you define > your PATH. >Hmmm, I beg to disagree. Also, $HOME is not appropriate when >searching another user's directory, cf: Yes, I know. You'll have to expand ~name yourself. >bash$ echo $PATH >/usr/1/kaul/bin:/usr/1/kaul/bin/sun3:/usr/bin/X11:/usr/local/gnu/bin:/usr/local/bin:~octtools/bin:~cad/bin:/usr/ucb:/usr/bin:/usr/etc:. >bash$ which magic >/usr/1/cad/bin/magic >bash$ magic >(saying ~cad/bin/magic gives the same result). Bash does the >expansion of the ~ before running the program. It is possible to Fine, I agree this works. That's not what Tom was talking about. Here's a script that demonstrates the problem: (BIFF is a filter I got off the net, a la jive) Script started on Tue Jan 22 18:06:38 1991 Z 1 phoenix:~/pub bash bash$ PATH=/usr/ucb:/bin:/usr/bin:/usr/princeton/bin:~/bin/sun4 bash$ echo $PATH /usr/ucb:/bin:/usr/bin:/usr/princeton/bin:~/bin/sun4 bash$ which BIFF /n/uffda/b/pfalstad/bin/sun4/BIFF bash$ ls | BIFF 101LAY0UT CENTREX CLIENTS C0MMANDS KEYREP MEGAHACK NEWPH0ENIX PHXPEF STRINGS TYPESCRIPT VI..REF. K0WABUNGA D00DZ!!!7 -- BIFF@BIT.NET BIFF@PSUVM.PSU.EDU BIFF@BIFFVM.BIT.NET BIFF+@ANDREW.CMU.EDU BIFF@PSUVM.ANDREW.PORTAL.COM.XZ.US.RUTGERS.ARPA.BITNET.EDU.UUCP MAN!WOMAN!BIRTH!DEATH!INFINITI!ROCKS!TREES!BIT.NET!BIFF@UUNET.UU.NET.EDU -- BIFF@BIT.NET BIFF@PSUVM.PSU.EDU BIFF@BIFFVM.BIT.NET BIFF+@ANDREW.CMU.EDU BIFF@PSUVM.ANDREW.PORTAL.COM.XZ.US.RUTGERS.ARPA.BITNET.EDU.UUCP MAN!WOMAN!BIRTH!DEATH!INFINITI!ROCKS!TREES!BIT.NET!BIFF@UUNET.UU.NET.EDU bash$ mail "/usr/spool/mail/pfalstad": 1 message 1 new >N 1 pfalstad Tue Jan 22 18:07 13/396 foo. & | BIFF Pipe to: "BIFF" /bin/sh: BIFF: not found "BIFF" 13/396 & q Saved 1 message in /n/uffda/b/pfalstad/mbox bash$ PATH=/usr/ucb:/bin:/usr/bin:/usr/princeton/bin:/u/pfalstad/bin/sun4 bash$ mail -f ~/mbox "/n/uffda/b/pfalstad/mbox": 1 message > 1 pfalstad Tue Jan 22 18:07 14/407 foo. & | BIFF Pipe to: "BIFF" FR0M PFALSTAD TUE JAN 22 18:07:27 1991 RECEIVED, L00K AT THIS D00DZ: FRUM B0W. D0N"T HAVE A K0W!!! (THE SIMPSUNZ AR THU KULEST!)PRINCET0N. C0WABUNGA!!!EDU BY PH0ENIX.PRINCET0N. C0WABUNGA!!!EDU (4.1/1.106) ID AA08726; TUE, 22 JAN 91 18:07:27 EST FR0M, L00K AT THIS D00DZ: PAUL FALSTAD <PFALSTAD> RECEIVED, L00K AT THIS D00DZ: BY B0W. D0N"T HAVE A K0W!!! (THE SIMPSUNZ AR THU KULEST!)PRINCET0N. C0WABUNGA!!!EDU (4.1/CS_002_CLUSTUR_CLIENT) ID AA02829; TUE, 22 JAN 91 18:07:25 EST DATE, L00K AT THIS D00DZ: TUE, 22 JAN 91 18:07:25 EST MESSAGE-ID, L00K AT THIS D00DZ: <9101222307.AA02829@B0W. D0N"T HAVE A K0W!!! (THE SIMPSUNZ AR THU KULEST!)PRINCET0N. C0WABUNGA!!!EDU> T0, L00K AT THIS D00DZ: PFALSTAD SUBJECT, L00K AT THIS D00DZ: F00. STATUS, L00K AT THIS D00DZ: R0 -- BIFF@BIT.NET BIFF@PSUVM.PSU.EDU BIFF@BIFFVM.BIT.NET BIFF+@ANDREW.CMU.EDU BIFF@PSUVM.ANDREW.PORTAL.COM.XZ.US.RUTGERS.ARPA.BITNET.EDU.UUCP MAN!WOMAN!BIRTH!DEATH!INFINITI!ROCKS!TREES!BIT.NET!BIFF@UUNET.UU.NET.EDU -- BIFF@BIT.NET BIFF@PSUVM.PSU.EDU BIFF@BIFFVM.BIT.NET BIFF+@ANDREW.CMU.EDU BIFF@PSUVM.ANDREW.PORTAL.COM.XZ.US.RUTGERS.ARPA.BITNET.EDU.UUCP MAN!WOMAN!BIRTH!DEATH!INFINITI!ROCKS!TREES!BIT.NET!BIFF@UUNET.UU.NET.EDU "BIFF" 14/407 & d & q "/n/uffda/b/pfalstad/mbox" complete bash$ Z 2 phoenix:~/pub exit script done on Tue Jan 22 18:09:56 1991 See the problem? mail, which uses execlp or popen or some such thing, can't find BIFF because it doesn't know how to expand ~'s in the path. I know bash does, but other programs don't. You either need to fix the c library or fix bash. >Obligatory plug for bash: it's worth it. It's a very nice shell, with >full emacs editing and very good vi editing if that's your dialect. >It's certainly more fun than tcsh, which I used before, and has a more >POSIX-ified behavior. There are still some bugs, although Chet's >version is nearly bug free, and version 1.06 is long overdue. I liked >it so much, I use the shell (or something to that effect). I mostly agree, although I'm partial to zsh for some strange reason. :-) -- Paul Falstad, pfalstad@phoenix.princeton.edu PLink:HYPNOS GEnie:P.FALSTAD In the heat of composition I find that I have inadvertently allowed myself to assume the form of a large centipede. I am accordingly dictating the rest to my secretary.
pfalstad@phoenix.Princeton.EDU (Paul Falstad) (01/23/91)
chet@po.CWRU.Edu wrote: >In article <5570@idunno.Princeton.EDU> pfalstad@phoenix.Princeton.EDU (Paul Falstad) writes: >>tchrist@convex.COM (Tom Christiansen) wrote: >>>From the keyboard of kaul@icarus.eng.ohio-state.edu (Rich Kaul): >>>That's odd -- if you have unexpanded tildes in your environment, >>>I wonder how you get system, popen, and execlp to work without >>>changing the C library. >>You don't, it seems. At least it didn't work for me. This is probably >>a bug in bash. You should use $HOME instead of ~ when you define >>your PATH. >You have to go through special pains to get an unexpanded tilde in >your PATH, since tilde expansion is performed on the rhs of assignment >statements. The only way you can get a tilde into your path is to >surround it with quotes. It might be a bug that double quotes can >inhibit the expansion. Well, you might have fixed it in the CWRU version, but my version (1.05.1) has the bug. Perhaps I need an update. But I would hardly call the following script "going through special pains." Script started on Tue Jan 22 19:48:33 1991 warning: could not update utmp entry Z 1 phoenix:~/src/zsh echo $PATH /n/uffda/b/pfalstad/scr:/u/pfalstad/bin/sun4:/usr/princeton/bin:/usr/ucb:/usr/bi n:/bin:/u/maruchck/scr:/u/cs320/bin:/u/subbarao/bin:/u/maruchck/bin:/usr/hosts:/ usr/princeton/bin/X11:/usr/etc:/etc Z 2 phoenix:~/src/zsh bash bash$ echo $PATH /n/uffda/b/pfalstad/scr:/u/pfalstad/bin/sun4:/usr/princeton/bin:/usr/ucb:/usr/bi n:/bin:/u/maruchck/scr:/u/cs320/bin:/u/subbarao/bin:/u/maruchck/bin:/usr/hosts:/ usr/princeton/bin/X11:/usr/etc:/etc bash$ PATH=~/scr:~/bin/sun4:/usr/princeton/bin:/usr/ucb:/usr/bin:/bin:~maruchck /scr:~cs320/bin:~subbarao/bin:~maruchck/bin:/usr/hosts:/usr/princeton/bin/X11:/ usr/etc:/etc bash$ echo $PATH /n/uffda/b/pfalstad/scr:~/bin/sun4:/usr/princeton/bin:/usr/ucb:/usr/bin:/bin:~ma ruchck/scr:~cs320/bin:~subbarao/bin:~maruchck/bin:/usr/hosts:/usr/princeton/bin/ X11:/usr/etc:/etc bash$ Z 3 phoenix:~/src/zsh exit script done on Tue Jan 22 19:49:30 1991 The ~ is expanded only for the first component in the PATH, not for the remaining components. Bash handles this fine, of course, but execlp does not. -- Paul Falstad, pfalstad@phoenix.princeton.edu PLink:HYPNOS GEnie:P.FALSTAD In the heat of composition I find that I have inadvertently allowed myself to assume the form of a large centipede. I am accordingly dictating the rest to my secretary.
brnstnd@kramden.acf.nyu.edu (Dan Bernstein) (01/23/91)
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, Objective fact, which anyone who's been reading this discussion can verify: After ``Or would you prefer double quoting?'' I presented several technical points in answer to Tom's complaint. Objective fact: Tom, who to me seems to be more interested in libel than in rational discussion, failed to quote those points. I wonder how often Tom perverts the discussion to prove his point? > 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? That is an... interesting... accusation, which, in case anyone cares, I flat-out deny. I'm perfectly willing to answer questions about my past that aren't on the moral and intellectual level of ``Have you stopped beating your wife?'' ``So, Tom, maybe you wouldn't be posting so much drivel if you hadn't been kicked out of Yale. Would you care to tell us all about that incident, Tom?'' > What ever did happen to rec.games.rpg > anyway? The one time I proposed it, it didn't seem feasible, so I didn't call for votes. > Unportable: I think not. In fact, perl runs on more machines than > sed and tr. Objective fact: sed and tr have been ported to MS-DOS and the Mac. Furthermore, they run on almost every BSD and System V machine. perl doesn't even come close. > I've not seen DOS or Macintosh ports of them, let alone > of the shell-from-hell you like to post things in. Objective fact: Tom just posted a statement (``perl runs on more machines than sed and tr'') which is objectively false, and which, if he had taken the time to check his facts, he would have known to be false. I wonder how many of Tom's statements are like that. > Unconventional: That's what the Fortran programmer said when he > first saw Algol, Pascal, C, etc. Fair enough. > 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? ``Gross: 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 un-grossness on your side, who can stand against you?'' ---Dan
brnstnd@kramden.acf.nyu.edu (Dan Bernstein) (01/23/91)
In article <8807@star.cs.vu.nl> maart@cs.vu.nl (Maarten Litmaath) writes: > In article <17373:Jan1908:30:3191@kramden.acf.nyu.edu>, > brnstnd@kramden.acf.nyu.edu (Dan Bernstein) writes: > )Hmmm. I've always been satisfied with the speed of > [_Excessively_ long line split.] > ) alias which 'echo `echo "$PATH" | tr : '\''\012'\'\ > ) ' | sed -e '\''s+$+/\!:1+'\'' -e '\''s:^:/.[.]:'\'\ > ) '` | sed '\''s:/../:/:g'\''' > This alias doesn't deal with aliases (easily fixed), but most importantly > it _fails_. No, it does exactly what it's meant to do. > % which passwd > /bin/passwd /usr/bin/passwd /etc/passwd > # How odd: /etc/passwd is executable! I like a which that points out non-executables in PATH, because it shows quite clearly any wasted exec()s. > % set path=($path .) > % cp /bin/true foo > % which foo > # Silence. It is a mistake to have . (or any other relative directories, if your system supports them) in your path. > Had you read the documentation of `which5', you would have known it's not > that trivial to get things right. Different people will prefer different behaviors of ``which''; no single behavior is right. (Should we say that which5 is wrong because it doesn't follow the BSD which man page?) ---Dan
tchrist@convex.COM (Tom Christiansen) (01/23/91)
The nature of my article was intended to echo Dan's: a bunch of childish insults (which he calls libel when I utter them) followed by some technical talk. Obviously, it's a wasted effort. But I just won't put up with insults. I thought fire with fire might place perspective and show why it's a bad thing. Dan ducked most technical issues. Let's try again. This is probably going to be more pearls before swine, but I'll try anyway. It's not a matter of quoting: it's one of complexity. The algorithm I used, which has been demo'd in shell, perl, and even the shell from hell, uses a straightforward decomposition of the problem. Others have concurred here that this approach seems more intuitive, legible, and maintainable than Dan's. Maarten also pointed out that Dan's solution made mistakes. Back to implementation language: do you really have csh on DOS, Mac's, etc? If so, why? Aren't you just spreading the sickness? If not, then that solution isn't going to work even if you should have sed and tr. Give me a list of BSD and SysV systems, Dan, on which Perl will not compile and run. I disblieve that there are a lot of them. In fact, I know of none, possibly modulo chez da Silva. --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@convex.com>)
chet@odin.INS.CWRU.Edu (Chet Ramey) (01/23/91)
Paul Falstad replied to a posting of mine: >The ~ is expanded only for the first component in the PATH, not for the >remaining components. Bash handles this fine, of course, but execlp >does not. You're right, of course. I had changed bash a while back to be more like ksh-86, which expanded tildes after colons when doing tilde expansion, but have since backed that change out after deciding it wasn't Posix compliant. (The ksh book says ksh88 doesn't expand tildes after colons, but I have no way to check that.) It might be better to expand tildes after colons, but bash is doing exactly what the documentation says it does. Chet -- Chet Ramey ``There's just no surf in Network Services Group Cleveland, U.S.A. ...'' Case Western Reserve University chet@ins.CWRU.Edu My opinions are just those, and mine alone.
brnstnd@kramden.acf.nyu.edu (Dan Bernstein) (01/24/91)
Tom, I posted a message saying ``I've always been satisfied with the speed of'' followed by my which alias. It was short and to the point; it was a direct followup to another article; and I hope somebody out there finds the alias useful. Then you started flaming, for no apparent reason. Why? We were having a perfectly pleasant technical discussion until you jumped in (again). Afterwards, you were making your usual pokes at the standard UNIX tools, so I poked fun at perl---and that pushed you over the edge. An entire article just to try to prove to the world how competent you are at making up insults. Is perl really that close to your heart? I always assume that criticism is meant to be constructive. Why don't you do the same? [End sermon. Begin light flames.] In article <1991Jan23.142528.12085@convex.com> tchrist@convex.COM (Tom Christiansen) writes: > The nature of my article was intended to echo Dan's: a bunch of > childish insults (which he calls libel when I utter them) I'm glad you admit that you were uttering a bunch of childish insults. > But > I just won't put up with insults. As anyone who has read this discussion can verify, any insults I've thrown at you have been direct responses to insults on your part. Witness this article, for example. > I thought fire with fire might > place perspective and show why it's a bad thing. Bullshit. You were just trying to protect your wounded di 'Scuse me. What I mean is, to put it simply, ``You started.'' The fact is that I was trying to contribute to a technical discussion, and you began flaming for no reason. > Dan ducked most technical issues. We can get into an infinite loop of ``No, you ducked first'' here; I'm sure that anyone who reviews the discussion will notice that you ducked first, though you probably believe exactly the opposite. > It's not a matter of quoting: it's one of complexity. The algorithm I > used, which has been demo'd in shell, perl, and even the shell from hell, > uses a straightforward decomposition of the problem. Others have > concurred here that this approach seems more intuitive, legible, and > maintainable than Dan's. Yes, one other person has agreed with you. So what? People have opinions. As I've told you in e-mail, I find shell solutions easy to deal with, for the same reason that you find perl solutions easy to deal with. > Maarten also pointed out that Dan's solution made mistakes. No, it did not make mistakes. What Maarten pointed out was that my ``which'' did something different from his ``which.'' > Back to implementation language: do you really have csh on DOS, Mac's, etc? > If so, why? Aren't you just spreading the sickness? If not, then that > solution isn't going to work even if you should have sed and tr. sh has been around for five years on DOS. Furthermore, as I've now told you twice and as you've repeatedly failed to acknowledge, my alias could be written in any shell with no effort. I only presented it as a csh alias because I use csh for interactive work on most systems. It seems to have escaped you that unquoting and quoting are five-letter commands in csh. Tom, you are failing to look beyond the simplest level of syntax. Do you criticize shars because they put X's before every line? Of course not: if you have trouble reading with the X's, you just unpack or pipe through sed. So why should you criticize a quoted alias, when all it takes is one ``alias'' command to see it without the quoting? > Give me a list of BSD and SysV systems, Dan, on which Perl will not > compile and run. Nobody's saying anything about where Perl *can* run. The question is where it *does* run. Stop perverting the argument. ---Dan
maart@cs.vu.nl (Maarten Litmaath) (01/24/91)
In article <9688:Jan2313:09:4391@kramden.acf.nyu.edu>, brnstnd@kramden.acf.nyu.edu (Dan Bernstein) writes: )[...] )> % which passwd )> /bin/passwd /usr/bin/passwd /etc/passwd )> # How odd: /etc/passwd is executable! ) )I like a which that points out non-executables in PATH, because it shows )quite clearly any wasted exec()s. I like a `which' that gives the right answer all the time, that is, the answer to the following question: When I type a command, say `foo', which file will be executed? )> % set path=($path .) )> % cp /bin/true foo )> % which foo )> # Silence. ) )It is a mistake to have . (or any other relative directories, if your )system supports them) in your path. Nonsense. It's a mistake to put `.' _before_ the standard directories. In my PATH `.' is the very last component. )> Had you read the documentation of `which5', you would have known it's not )> that trivial to get things right. ) )Different people will prefer different behaviors of ``which''; [...] Agreed. But some types of behavior are questionable at best, ridiculous at worst. -- kinnersley@kuhub.cc.ukans.edu (Bill Kinnersley): "Do phonograph turntables turn the other way in Australia?" gjh@krebs.acc.Virginia.EDU (Galen J. Hekhuis) "How do you think satanic messages were discovered on records?"
pfalstad@phoenix.Princeton.EDU (Paul Falstad) (01/24/91)
maart@cs.vu.nl (Maarten Litmaath) wrote: >In article <9688:Jan2313:09:4391@kramden.acf.nyu.edu>, > brnstnd@kramden.acf.nyu.edu (Dan Bernstein) writes: >)> % which passwd >)> /bin/passwd /usr/bin/passwd /etc/passwd >)> # How odd: /etc/passwd is executable! >)I like a which that points out non-executables in PATH, because it shows >)quite clearly any wasted exec()s. >I like a `which' that gives the right answer all the time, that is, the >answer to the following question: > When I type a command, say `foo', which file will be executed? Good point. But if you do agree with Dan, and want a which that points out non-executables in PATH, you can make a simple easy obvious change to Tom's perl script (take out the -x, move the $path assigment) to make it do that. His is much more flexible. If you don't agree with Dan, and want to fix the csh version to exclude non-executables, after deciphering the csh brain-damage you'd discover that there's no way to change it. Perhaps since Dan can't fix his which, he's decided that it's OK the way it is. (That's only a suggestion. He probably does like which to have that behavior.) But Tom's solution can easily be changed to have either behavior. >)> % set path=($path .) >)> % cp /bin/true foo >)> % which foo >)> # Silence. >)It is a mistake to have . (or any other relative directories, if your >)system supports them) in your path. That's nice, but the fact is many people do have . in their path (it's last in the default path at our site). You're saying, "Well, my version doesn't work if you have . in your path, so don't put . in your path." "Doctor, it hurts when I do this." "So don't do that." I agree that's its not too smart to have . in your path. (I don't.) But for those who do, it's all the more important for which to report executables in the current directory, to make sure you're not about to execute a trojan horse by accident. In any case, your version should do something sensible when someone has . in his path; instead it does something strange, and it's hard for someone who doesn't speak csh to figure out why after looking at your code. Again I could ask, does your csh alias behave this way because you designed it to, or because there's no other way it could act? The perl solution could easily be changed to print a blank line or print garbage or coredump if you're stupid enough to have . in your path; your solution is not so flexible. >)> Had you read the documentation of `which5', you would have known it's not >)> that trivial to get things right. >) >)Different people will prefer different behaviors of ``which''; [...] > >Agreed. But some types of behavior are questionable at best, ridiculous >at worst. Dan prefers the behavior of his which because the crufty language it's written in allows no other behavior. How convenient. Yet different people can easily change the perl solution to have the different behaviors they prefer. That seems much more sensible to me. Aren't flame wars fun? -- Paul Falstad, pfalstad@phoenix.princeton.edu PLink:HYPNOS GEnie:P.FALSTAD In the heat of composition I find that I have inadvertently allowed myself to assume the form of a large centipede. I am accordingly dictating the rest to my secretary. 409 shift/reduce, 62 reduce/reduce conflicts. Beat that!
brnstnd@kramden.acf.nyu.edu (Dan Bernstein) (01/24/91)
Ya want other behaviors? Fine, ya get other behaviors. These all use the same strategy as the original. Original: echo `echo "$PATH" | tr : '\012' | sed -e 's:$:/!:1': -e 's:^:/.[.]:'`\ | sed 's:/\.\./:/:g' The same thing, but with marks from ls showing the type of each file: ls -dF `echo "$PATH" | tr : '\012' | sed -e 's:$:/!:1': -e 's:^:/.[.]:'`\ | sed 's:/\.\./:/:g' The same thing, but following symbolic links: ls -dFL `echo "$PATH" | tr : '\012' | sed -e 's:$:/!:1': -e 's:^:/.[.]:'`\ | sed 's:/\.\./:/:g' The same thing, but showing only executables: ls -dFL `echo "$PATH" | tr : '\012' | sed -e 's:$:/!:1': -e 's:^:/.[.]:'`\ | sed -n -e 's:/\.\./:/:g' -e '/*$/p' The same thing, but removing the *: ls -dFL `echo "$PATH" | tr : '\012' | sed -e 's:$:/!:1': -e 's:^:/.[.]:'`\ | sed -n -e 's:/\.\./:/:g' -e 's/*$//p' The same thing, but showing only the first executable: ls -dFL `echo "$PATH" | tr : '\012' | sed -e 's:$:/!:1': -e 's:^:/.[.]:'`\ | sed -n -e 's:/\.\./:/:g' -e 's/*$//p' | head -1 Same as the first one, but converting . in PATH into the actual cwd: setenv WD "`pwd`" echo `echo "$PATH" | tr : '\012' | sed -e 's:^\.$:'"$WD": -e 's:$:/!:1': -e 's:^:/.[.]:'`\ | sed 's:/\.\./:/:g' The same thing, but with ./ instead of `pwd`/: echo `echo "$PATH" | tr : '\012' | sed -e 's:^\.$:'"$WD": -e 's:$:/!:1': -e 's:^:/.[.]:'`\ | sed -e 's:/\.\./:/:g' -e 's:^'"$WD"'/:./:g' You can easily combine these to make other behaviors if you want, e.g., to just show the first executable including in ., or whatever. If you want to quote a command for csh or sh, e.g., to make a csh alias, or to pass something to sh -c or csh -cf: Use quote and makealias, which have been running around since I posted them in 1988. You can pick up a pile of random shell tricks from pub/hier/misc/faq-shell via anonymous ftp to 128.122.128.22. If you want to put these in a script instead: Replace !:1 with '"$1"', and top the script with #!/bin/csh -f. If you want to accept aliases from .cshrc: Same, but remove the -f. In article <5648@idunno.Princeton.EDU> pfalstad@phoenix.Princeton.EDU (Paul Falstad) writes: > If you don't agree with Dan, and want > to fix the csh version to exclude non-executables, after deciphering the csh > brain-damage you'd discover that there's no way to change it. Again, the deciphering is as simple as ``alias which'', but it's a fair accusation. Wrong, but fair. > Perhaps > since Dan can't fix his which, he's decided that it's OK the way it is. An interesting thought. > (That's only a suggestion. He probably does like which to have that behavior.) Obviously. > But Tom's solution can easily be changed to have either behavior. So what? So can any reasonable solution. > That's nice, but the fact is many people do have . in their path (it's > last in the default path at our site). You're saying, "Well, my version > doesn't work if you have . in your path, so don't put . in your path." > "Doctor, it hurts when I do this." "So don't do that." Again, wrong, though fair. > Again I could ask, does your csh alias behave this way because you > designed it to, or because there's no other way it could act? I think I've answered that question. > >)> Had you read the documentation of `which5', you would have known it's not > >)> that trivial to get things right. > >)Different people will prefer different behaviors of ``which''; [...] > >Agreed. But some types of behavior are questionable at best, ridiculous > >at worst. > Dan prefers the behavior of his which because the crufty language it's > written in allows no other behavior. Now, now, don't make silly accusations without thinking things through first. ---Dan
brnstnd@kramden.acf.nyu.edu (Dan Bernstein) (01/24/91)
In article <8833@star.cs.vu.nl> maart@cs.vu.nl (Maarten Litmaath) writes: > I like a `which' that gives the right answer all the time, that is, the > answer to the following question: > When I type a command, say `foo', which file will be executed? #!/bin/csh setenv WD "`pwd`" ls -dFL `echo "$PATH" | tr : '\012' | sed -e 's:^\.$:'"$WD": -e 's:$:/'"$1": -e 's:^:/.[.]:'`\ | sed -e 's:/\.\./:/:g' -e 's:^'"$WD"'/:./:g' -e 's/*$//p' | head -1 If this is missing any features you want, just say what they are. On systems without symbolic links you probably have to leave out the -L; other than that this should be reasonably portable. (I agree, btw, that it's worth rewriting something like this in C if the shell script isn't efficient enough.) > )It is a mistake to have . (or any other relative directories, if your > )system supports them) in your path. > Nonsense. It's a mistake to put `.' _before_ the standard directories. > In my PATH `.' is the very last component. Ah, so the moment you make a typing mistake you execute anybody's program? ---Dan
pfalstad@phoenix.Princeton.EDU (Paul Falstad) (01/25/91)
brnstnd@kramden.acf.nyu.edu (Dan Bernstein) wrote: >Same as the first one, but converting . in PATH into the actual cwd: > > setenv WD "`pwd`" > echo `echo "$PATH" | tr : '\012' | sed -e 's:^\.$:'"$WD": -e 's:$:/!:1': -e 's:^:/.[.]:'`\ > | sed 's:/\.\./:/:g' This is not really a change in optional behavior, it is a bug fix. Your which should act the right way if you have . in your path. >Original: > > echo `echo "$PATH" | tr : '\012' | sed -e 's:$:/!:1': -e 's:^:/.[.]:'`\ > | sed 's:/\.\./:/:g' >The same thing, but removing the *: > > ls -dFL `echo "$PATH" | tr : '\012' | sed -e 's:$:/!:1': -e 's:^:/.[.]:'`\ > | sed -n -e 's:/\.\./:/:g' -e 's/*$//p' (I could point out that if you have files ending in * in your path, this acts weird, but I won't. For the most part it works fine, I'm sure. I was wrong to imply that this was impossible with standard tools.) This is kind of confusing. In order to print only executables, you have changed the echo to an ls -dFL and added another expression to the second sed. It is not at all intuitive what the difference between these two versions are. I suppose someone smart enough to deduce what your original did could figure out what the second one did, but it's not obvious. However, with Tom's, the difference is: < printf "$path\n" if -x ($path="$dir/$file"); --- > printf "$dir/$file\n"; The difference is obvious; you've just removed the test. With Tom's, to remove the checking to see if the file is executable or not, you just remove the test. In yours, to put in the checking, you change 'echo' to 'ls -dFL' and add another expression to your sed command. This is not obvious. >The same thing, but showing only the first executable: > > ls -dFL `echo "$PATH" | tr : '\012' | sed -e 's:$:/!:1': -e 's:^:/.[.]:'`\ > | sed -n -e 's:/\.\./:/:g' -e 's/*$//p' | head -1 This is a bit inefficient; all you've done here is add one more process to filter the output of the original. I doubt anyone would choose this method as a standard implementation for which. >You can easily combine these to make other behaviors if you want, e.g., >to just show the first executable including in ., or whatever. Certainly not as easily as changing the perl script. These are shell hacks, not programs. The reason I call them hacks, and part of the reason they're confusing is that they depend on a bug in csh for their operation! Let's say we try to figure out how the original (buggy) version works: > echo `echo "$PATH" | tr : '\012' | sed -e 's:$:/!:1': -e 's:^:/.[.]:'`\ > | sed 's:/\.\./:/:g' I know as a shell writer I should know at first glance what this does, but I must confess I had to break it down. Let's see: 1 phoenix:~/News echo "$PATH" | tr : '\012' | sed -e 's:$:/ls': -e 's:^:/.[.]:' /.[.]/n/uffda/b/pfalstad/scr/ls /.[.]/n/uffda/b/pfalstad/bin/sun4/ls /.[.]/usr/princeton/bin/ls /.[.]/usr/ucb/ls /.[.]/usr/bin/ls /.[.]/bin/ls /.[.]/u/maruchck/scr/ls /.[.]/u/cs320/bin/ls /.[.]/u/subbarao/bin/ls /.[.]/u/maruchck/bin/ls /.[.]/usr/hosts/ls /.[.]/usr/princeton/bin/X11/ls /.[.]/usr/etc/ls /.[.]/etc/ls 3 phoenix:~/News echo `echo /.[.]/etc/ls` echo: No match. 4 phoenix:~/News echo `echo '/.[.]/etc/ls'` 5 phoenix:~/News exit What's going on? It turns out that your version depends on a bug in csh, or at least a stupid feature. I don't think that the output of `...` substitution should be globbed at all (It's not obvious that it should be), and if it is, and there is no match, it should print an error message. It's this same 'feature' that requires you to put 'set noglob' and 'unset noglob' around eval `tset -s` in your .login. This bug has been fixed in some versions, including itcsh. The only reason I could figure out how your alias works is because I've taken a lot of time studying the standard shells, and have read the csh bug list. Writing a shell didn't hurt either. I would never write a script that used a csh bug for part of its operation and then post it to the net as an example. >If you want to put these in a script instead: Replace !:1 with '"$1"', >and top the script with #!/bin/csh -f. > >If you want to accept aliases from .cshrc: Same, but remove the -f. What do you mean? You mean, change your implementation so it uses aliases from .cshrc? I don't see the difference this makes. >> (That's only a suggestion. He probably does like which to have that behavior.) > >Obviously. Wasn't obvious from your article. You should have fixed your solution first, and then explained why it's bad to have . in your path. You sounded like a lazy programmer trying to get out of making a bug fix. I know the feeling. :-) >> But Tom's solution can easily be changed to have either behavior. > >So what? So can any reasonable solution. You're not really changing the solution, you're just filtering the output. Tom's can be filtered as well. If you want to write a nice version of which that uses standard tools (which I have no qualms about, I'm no perl groupie), you should use a loop. It can be done in csh; SunOS /usr/ucb/which is a csh script. Better yet, use a decent shell. If you like your version because it's fast and it works the way you want it to, that's fine. But you must admit, it's hardly an example of good code. I can't see how any csh hack that can't easily be translated into a decent shell like sh or ksh can be called good code. -- Paul Falstad, pfalstad@phoenix.princeton.edu PLink:HYPNOS GEnie:P.FALSTAD In the heat of composition I find that I have inadvertently allowed myself to assume the form of a large centipede. I am accordingly dictating the rest to my secretary. 409 shift/reduce, 62 reduce/reduce conflicts. Beat that!
subbarao@phoenix.Princeton.EDU (Kartik Subbarao) (01/25/91)
>>Obligatory plug for bash: it's worth it. It's a very nice shell, with >>full emacs editing and very good vi editing if that's your dialect. >>It's certainly more fun than tcsh, which I used before, and has a more >>POSIX-ified behavior. There are still some bugs, although Chet's >>version is nearly bug free, and version 1.06 is long overdue. I liked >>it so much, I use the shell (or something to that effect). > Cough Cough! Ahem Ahem! I *beg* to differ. Rather, I *demand* to differ. *Obligatory?* Yeah right. After you get frustrated half an hour with its damn non-destructive backspace, then ditz with it another hour on its half-assed command line editor, and you're left with a huge piece of code that's not worth its weight in ^@'s. Bourne Again? More like Burned Again. Get tcsh. Now that's a real shell. >I mostly agree, although I'm partial to zsh for some strange reason. :-) Wonder why :-) Once Paul finishes a decent line editor, I'll use it too. -Kartik -- internet# find . -name core -exec cat {} \; |& tee /dev/tty* subbarao@{phoenix or gauguin}.Princeton.EDU -|Internet kartik@silvertone.Princeton.EDU (NeXT mail) -| SUBBARAO@PUCC.BITNET - Bitnet
brnstnd@kramden.acf.nyu.edu (Dan Bernstein) (01/25/91)
In article <5657@idunno.Princeton.EDU> pfalstad@phoenix.Princeton.EDU (Paul Falstad) writes: > brnstnd@kramden.acf.nyu.edu (Dan Bernstein) wrote: > >Same as the first one, but converting . in PATH into the actual cwd: > > setenv WD "`pwd`" > > echo `echo "$PATH" | tr : '\012' | sed -e 's:^\.$:'"$WD": -e 's:$:/!:1': -e 's:^:/.[.]:'`\ > > | sed 's:/\.\./:/:g' > This is not really a change in optional behavior, it is a bug fix. Your > which should act the right way if you have . in your path. There was no bug to fix. It is a change in optional behavior. I happen to think that it's stupid for the output of which to be relative to your current directory; by that criterion, any version of which that pays attention to . is wrong. But different people want different behaviors. > This is kind of confusing. In order to print only executables, you have > changed the echo to an ls -dFL and added another expression to the > second sed. No. The changes were explained in the order that I did them, one at a time. Say you know that foo exists. echo foo just prints foo. ls -dF foo adds a file type mark. (I said the same thing in the first article.) Do you understand the first change now? Now say you have a file list from ls -dF. To extract only the executables, you check for * at the end of the line. The regexp for this is \*$. Do you understand the second change now? > However, with Tom's, the difference is: > < printf "$path\n" if -x ($path="$dir/$file"); > > printf "$dir/$file\n"; Yeah, so? That's more characters changed than in my version. Intuitively, though, using $path is analogous to the middle stage with ls instead of echo, and the -x test is analogous to the * extraction. (Btw, are you so sure that your change is correct?) > >The same thing, but showing only the first executable: > > ls -dFL `echo "$PATH" | tr : '\012' | sed -e 's:$:/!:1': -e 's:^:/.[.]:'`\ > > | sed -n -e 's:/\.\./:/:g' -e 's/*$//p' | head -1 > This is a bit inefficient; all you've done here is add one more process > to filter the output of the original. You can add it to the sed if you want; I didn't bother. > I doubt anyone would choose this > method as a standard implementation for which. No shit. Standard implementations of commonly used programs are written in C, because the world doesn't want its computers to be twice as slow. [ my commands are shell hacks because they depend on a csh bug ] [ that bug is the fact that the result of `` is globbed ] That isn't a bug; it's a documented feature. You can easily avoid it if you want. Paul, something isn't a hack just because it depends on a documented feature that you don't appreciate. > You mean, change your implementation so it uses > aliases from .cshrc? No, that's not what I said. > >> (That's only a suggestion. He probably does like which to have that behavior.) > >Obviously. > Wasn't obvious from your article. Yes, it was; I said so, in plain English. > You > sounded like a lazy programmer trying to get out of making a bug fix. FLAME ON You and Tom are coming across as so lazy that you'd rather waste thousands of dollars of money around the world arguing with facts than spending the two minutes it would take you to figure things out on your own. Any competent shell programmer can use filters, and I'm not going to teach you tricks that you can easily figure out for yourself. FLAME OFF > >> But Tom's solution can easily be changed to have either behavior. > >So what? So can any reasonable solution. > You're not really changing the solution, you're just filtering the > output. Paul, given that my solution is composed of filters, doesn't it strike you as sensible that changing the solution means changing the filters? > SunOS /usr/ucb/which is a csh script. Yeah, and slow as per---I mean molasses. > But you must admit, it's > hardly an example of good code. Why? You haven't given any reason for me to admit such a thing. > I can't see how any csh hack that can't > easily be translated into a decent shell like sh or ksh can be called > good code. ``I can't see how any perl hack that can't easily be translated into a decent language like C can be called good code.'' Who tf cares? ---Dan
pfalstad@burst.Princeton.EDU (Paul Falstad) (01/25/91)
subbarao@phoenix.Princeton.EDU (Kartik Subbarao) wrote: >Cough Cough! Ahem Ahem! I *beg* to differ. Rather, I *demand* to differ. [ other b.s. deleted ] I don't know this person, he just happens to have an account on the same machine as I do. Please don't flame him, he didn't mean it. >>I mostly agree, although I'm partial to zsh for some strange reason. :-) >Wonder why :-) Once Paul finishes a decent line editor, I'll use it too. Don't let that turn you off. -- Paul Falstad, pfalstad@phoenix.princeton.edu PLink:HYPNOS GEnie:P.FALSTAD "And she's always on about men following her. I don't know what she thinks they're going to do to her. Vomit on her, Basil, says."-Flowery Twats
subbarao@phoenix.Princeton.EDU (Kartik Subbarao) (01/25/91)
In article <17687:Jan2414:33:5091@kramden.acf.nyu.edu> brnstnd@kramden.acf.nyu.edu (Dan Bernstein) writes: >In article <8833@star.cs.vu.nl> maart@cs.vu.nl (Maarten Litmaath) writes: >> )It is a mistake to have . (or any other relative directories, if your >> )system supports them) in your path. >> Nonsense. It's a mistake to put `.' _before_ the standard directories. >> In my PATH `.' is the very last component. > >Ah, so the moment you make a typing mistake you execute anybody's >program? I make most of my mistakes typing commands in a consistent fashion (i.e, mroe for more, dc for cd, etc..) I simply alias the few consistent mistakes that I make. Most of the times when I want to execute stuff "in the current directory", its when I'm either working on a project, or have ftp'd something from the net and am in the process of compiling, etc.. I *really* don't feel like typing './a.out', or './xneatapplication'. Also, most people don't go to lengths as to do stupid things like put trojan horses in /tmp -- even if they did, I really don't care that much. I operate on the basis that my account is currently in the capability of being gotten into by anyone, and so I never have any security problems. I never leave anything around in my account that I feel is so extremely private that nobody should see it (UNIX certainly is not the place to keep that kind of stuff). Most of my account is readable. The only person who I'd REALLY suggest this for is root. Certainly, for me, the convenience of NOT having to type `./' everytime that I execute something in the current directory GREATLY overweighs any worry I have over some nerd wanting to break into my account. -Kartik -- internet# find . -name core -exec cat {} \; |& tee /dev/tty* subbarao@{phoenix or gauguin}.Princeton.EDU -|Internet kartik@silvertone.Princeton.EDU (NeXT mail) -| SUBBARAO@PUCC.BITNET - Bitnet
pfalstad@burst.Princeton.EDU (Paul Falstad) (01/25/91)
brnstnd@kramden.acf.nyu.edu (Dan Bernstein) wrote: >In article <5657@idunno.Princeton.EDU> pfalstad@phoenix.Princeton.EDU (Paul Falstad) writes: >> brnstnd@kramden.acf.nyu.edu (Dan Bernstein) wrote: >There was no bug to fix. It is a change in optional behavior. I happen >to think that it's stupid for the output of which to be relative to your >current directory; by that criterion, any version of which that pays >attention to . is wrong. But different people want different behaviors. No, you think it's stupid for someone to have . in their path, and I agree. But if a person does have . in their path, your version should work properly. I think it's stupid for people to play nethack, but it wouldn't be good to write a shell that dumps core whenever someone types "nethack." Unless you're saying that "I will use this version of which because it's faster and because it works with my path because it doesn't have . in it." Then I agree. >[ explains how it works ] Yes, I did figure it out, but it took a while. The perl solution was obvious, at least to me. >(Btw, are you so sure that your change is correct?) No, I didn't bother to test it. I don't know perl. >That isn't a bug; it's a documented feature. You can easily avoid it if >you want. How? (genuine question) Is there a way to make csh not glob the results of command substitution but have usual globbing work fine? Also, this feature is not documented, at least not in my manual. If I'm wrong please show me where it's documented. Any feature that cannot be turned off is a bug. >> You mean, change your implementation so it uses >> aliases from .cshrc? > >No, that's not what I said. What did you say? >You and Tom are coming across as so lazy that you'd rather waste >thousands of dollars of money around the world arguing with facts than >spending the two minutes it would take you to figure things out on your >own. Any competent shell programmer can use filters, and I'm not going >to teach you tricks that you can easily figure out for yourself. I spent the two minutes figuring it out, and now I'm wasting thousands of dollars of money around the world hoping to prevent others from having to do the same. >Yeah, and slow as per---I mean molasses. I did say SunOS. >``I can't see how any perl hack that can't easily be translated into a >decent language like C can be called good code.'' Who tf cares? I certainly don't. I'm no perl groupie, as I said. In fact, my longest perl script is one line. I just like flame wars. :-) I really don't give a fuck about this whole discussion, nor does 99% of the net, but it's fun to hear people having flame wars over such trivialities. I'm saving this thread for posterity. Flame on! -- Paul Falstad, pfalstad@phoenix.princeton.edu PLink:HYPNOS GEnie:P.FALSTAD "And she's always on about men following her. I don't know what she thinks they're going to do to her. Vomit on her, Basil, says."-Flowery Twats
tchrist@convex.COM (Tom Christiansen) (01/25/91)
From the keyboard of brnstnd@kramden.acf.nyu.edu (Dan Bernstein): :Ya want other behaviors? Fine, ya get other behaviors. These all use the :same strategy as the original. [ many nice pipe examples that no novice will ever decipher. ] :> But Tom's solution can easily be changed to have either behavior. : :So what? So can any reasonable solution. And your solution, Dan, has not yet been proven to be such. Leave the programming langauge at sh if it will eliminate an irrevlant complaint of yours. The principal point is that there is a straightforward algorithm employed here that a relatively recently initiated unix user can easily read and understand. To say "for each dir in path, print the pathname if there is an exececutable file of the target name there" is much easier to grok. It's called top-down programming. The tr/sed/sed/blah munging is not as simple, and not as obvious. In fact, it's several times less obvious. Take both to a novice and ask their opinion on this. I challenge you. --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@convex.com>)
tchrist@convex.COM (Tom Christiansen) (01/25/91)
From the keyboard of brnstnd@kramden.acf.nyu.edu (Dan Bernstein): :> However, with Tom's, the difference is: :> < printf "$path\n" if -x ($path="$dir/$file"); :> > printf "$dir/$file\n"; : :Yeah, so? That's more characters changed than in my version. :Intuitively, though, using $path is analogous to the middle stage with :ls instead of echo, and the -x test is analogous to the * extraction. No, it's not in the least bit intuitive. No series of filters strung together like that using 4 regexps and multiple evaluation will ever be as easy to understand as my solution. On that I stand. :> > ls -dFL `echo "$PATH" | tr : '\012' | sed -e 's:$:/!:1': -e 's:^:/.[.]:'`\ :> > | sed -n -e 's:/\.\./:/:g' -e 's/*$//p' | head -1 It's also slower than sin. :No shit. Standard implementations of commonly used programs are written :in C, because the world doesn't want its computers to be twice as slow. So why didn't you post a solution in C then? The perl solution is much faster than your grody hack, if you're honestly concerned about speed. I'm also concerned about complexity. It doesn't make one bit of difference whether a command executed as infrequently as which takes .03 seconds instead of .06 seconds. :You and Tom are coming across as so lazy that you'd rather waste :thousands of dollars of money around the world arguing with facts than :spending the two minutes it would take you to figure things out on your :own. Any competent shell programmer can use filters, and I'm not going :to teach you tricks that you can easily figure out for yourself. Just what is this claptrap? I can't make any sense of it. It has no relevance on anything going on here. Dan's just being insulting and attacking wildly again. He attempts to persuade by bashing you on the head and lobbing insults. What a wonderful world it would be if everyone would do this. --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@convex.com>)
tale@rpi.edu (David C Lawrence) (01/25/91)
In <5612@idunno.Princeton.EDU> pfalstad@phoenix.Princeton.EDU (Paul Falstad): The ~ is expanded only for the first component in the PATH, not for the remaining components. Bash handles this fine, of course, but execlp does not. Not only that, ~ also isn't _always_ expanded if first. Try VAR=~:~. It only seems to do it if ~ is followed by a username or by /. Many moons ago I just decided to use this in every login shell environment I had to set my environment variables: function tilde { echo "$@" | /usr/bin/tr ' ' : } PATH=`tilde ~tale/bin /usr/local/gnu/bin /usr/bin/X11 /usr/local/bin /usr/etc /usr/bin /usr/ucb /bin /usr/5bin ~weltyc/bin .` Used similary for MANPATH, TEXINPUTS, et cetera. The "function" part has changed for each flavour of shell, but the basic method is there. -- (setq mail '("tale@cs.rpi.edu" "tale@ai.mit.edu" "tale@rpitsmts.bitnet"))
brnstnd@kramden.acf.nyu.edu (Dan Bernstein) (01/26/91)
In article <5688@idunno.Princeton.EDU> pfalstad@burst.Princeton.EDU (Paul Falstad) writes: > >[ explains how it works ] > Yes, I did figure it out, but it took a while. The perl solution was > obvious, at least to me. > >(Btw, are you so sure that your change is correct?) > No, I didn't bother to test it. I don't know perl. Well, your ``obvious'' change is wrong. This says something about the maintainability of the perl solution. > >That isn't a bug; it's a documented feature. You can easily avoid it if > >you want. > How? (genuine question) Is there a way to make csh not glob the results > of command substitution but have usual globbing work fine? Hint: To stop foo from being globbed, you put double-quotes around it. > Also, this > feature is not documented, at least not in my manual. Frighteningly bad csh manual you have if it doesn't mention double quotes. > >You and Tom are coming across as so lazy that you'd rather waste > >thousands of dollars of money around the world arguing with facts than > >spending the two minutes it would take you to figure things out on your > >own. Any competent shell programmer can use filters, and I'm not going > >to teach you tricks that you can easily figure out for yourself. > I spent the two minutes figuring it out, and now I'm wasting thousands > of dollars of money around the world hoping to prevent others from > having to do the same. Sorry, but all you've shown in this article is that you don't know how to use double-quotes to prevent globbing. ---Dan
brnstnd@kramden.acf.nyu.edu (Dan Bernstein) (01/26/91)
In article <1991Jan25.080151.11595@convex.com> tchrist@convex.COM (Tom Christiansen) writes: > From the keyboard of brnstnd@kramden.acf.nyu.edu (Dan Bernstein): > :Ya want other behaviors? Fine, ya get other behaviors. These all use the > :same strategy as the original. > [ many nice pipe examples that no novice will ever decipher. ] Who tf cares? Maybe you have novices maintaining your software at Convex, but I don't really care whether a solution is obvious or even comprehensible to novices. It's much more important that people be able to understand the interface. > :> But Tom's solution can easily be changed to have either behavior. > :So what? So can any reasonable solution. > And your solution, Dan, has not yet been proven to be such. Huh? Non sequitur. What does program proving have to do with whether a program can be changed to give a different behavior? > Leave the > programming langauge at sh if it will eliminate an irrevlant complaint of > yours. Huh? Wtf is irrevlant? Can anyone understand that sentence? > To say "for each dir in path, print the pathname if > there is an exececutable file of the target name there" is much easier to > grok. Huh? Much easier than what? My solution translates as ``Add the target name to every dir in path, glob to select only the files that exist, print.'' So you're working one element at a time while I'm working with the entire set of directories at once. This isn't a real difference. > Take both to a novice and ask their opinion on this. I > challenge you. I don't know any UNIX novices who've learned test yet, and your solution depends on -x. What do you mean by a novice? ---Dan
chip@tct.uucp (Chip Salzenberg) (01/26/91)
According to brnstnd@kramden.acf.nyu.edu (Dan Bernstein):
>There was no bug to fix. It is a change in optional behavior.
I have not seen anyone convince Tom Neff (or Dan Bernstein) of
anything different that the thoughts that they were born with.
-- an E-correspondent of Kent Paul Dolan
--
Chip Salzenberg at Teltronics/TCT <chip@tct.uucp>, <uunet!pdn!tct!chip>
"If Usenet exists, then what is its mailing address?" -- me
"c/o The Daily Planet, Metropolis." -- Jeff Daiell
wilkes@mips.COM (John Wilkes) (01/26/91)
In article <5648@idunno.Princeton.EDU> pfalstad@phoenix.Princeton.EDU (Paul Falstad) writes: > >Aren't flame wars fun? "Arguments are full of words and each person is sure he's the only one who knows what the words mean. Each word is a basket of eels, as far as I'm concerned. Everybody gets to grab just one eel and that's his interpretation, and he'll fight to the death for it." from _Stallion_Gate_ by Martin Cruz Smith -wilkes <wilkes@mips.com>
tchrist@convex.COM (Tom Christiansen) (01/26/91)
From the keyboard of brnstnd@kramden.acf.nyu.edu (Dan Bernstein):
:In article <1991Jan25.080151.11595@convex.com> tchrist@convex.COM (Tom Christiansen) writes:
:> From the keyboard of brnstnd@kramden.acf.nyu.edu (Dan Bernstein):
:> :Ya want other behaviors? Fine, ya get other behaviors. These all use the
:> :same strategy as the original.
:> [ many nice pipe examples that no novice will ever decipher. ]
:
:Who tf cares? Maybe you have novices maintaining your software at
:Convex, but I don't really care whether a solution is obvious or even
:comprehensible to novices. It's much more important that people be able
:to understand the interface.
How much mud can the mud-slinger sling? How many insults can be lobbed by
this sadly disturbed individual? Dragging in corporate affiliation like
this name is but another childish tactic, and it's not even close to
correct. I've a much wider perspective at work here than simply where I
work. Dan's original code had 30 quotes, 9 backslashes, and an
indirection is ugly: this in itself makes it hard to understand by almost
anyone there is. There are a lot of UNIX users out there, and I see no
reason to make it harder than it needs to be. I've taught UNIX to
maybe a thousand new users in the last 5 years, and this is the kind
of stuff that turns them off.
:> :> But Tom's solution can easily be changed to have either behavior.
:> :So what? So can any reasonable solution.
:> And your solution, Dan, has not yet been proven to be such.
:
:Huh? Non sequitur. What does program proving have to do with whether a
:program can be changed to give a different behavior?
Your approach has not been proven to be a reasonable solution. It's
obfuscated. You're expressing an alternate algorithm to solve a problem.
It's failing lies in its obfuscation. It doesn't have to be that way.
You can write this in many languages in a much more straightforward
way. But you want 30 quotes in this.
:> Leave the
:> programming langauge at sh if it will eliminate an irrevlant complaint of
:> yours.
:
:Huh? Wtf is irrevlant? Can anyone understand that sentence?
It means irrelevant, Dan. Doesn't seem to me like a hard typo to
pattern-match out something that makes sense. But maybe your gifts
lie in other directions, like senseless attacks.
--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@convex.com>)
brnstnd@kramden.acf.nyu.edu (Dan Bernstein) (01/27/91)
In article <1991Jan26.093659.26192@convex.com> tchrist@convex.COM (Tom Christiansen) writes: > How much mud can the mud-slinger sling? How many insults can be lobbed by > this sadly disturbed individual? Dragging in corporate affiliation like > this name is but another childish tactic, and it's not even close to > correct. Objective facts: Every nasty technique you accuse me of using, you used first. You started flaming first, you started insulting first, you started dragging in affiliation first. Any reader can verify these firsts. The fact, is, Tom, that every step this discussion has taken towards USENET hell, you've dragged it down that step. ``Sadly disturbed.'' ``Childish.'' Wow. I think Freud invented the word ``projection'' for Tom's behavior. > Dan's original code had 30 quotes, 9 backslashes, and an > indirection is ugly: this in itself makes it hard to understand by almost > anyone there is. Are you saying that any code with 30 quotes, 9 backslashes, and indirection is hard to understand? You haven't presented any logic in support of your position, so either you're being irrational or you're making an idiotic generalization. (Of course, anyone who knows how to type ``alias foo'' can remove almost all the quotes, backslashes, and indirection before trying to understand the alias, but I take it that this wizardly technique is too advanced for you.) > Your approach has not been proven to be a reasonable solution. Objective fact: You started criticizing other people's code first. You started criticizing code on subjective grounds (like whether it's ``reasonable'') first. > You're expressing an alternate algorithm to solve a problem. As I told you and as you failed to acknowledge, the difference between my algorithm and yours is that I'm taking the entire path at once while you're taking one directory at a time. To any mathematician this is a trivial difference; sorry if it doesn't seem so trivial to you. > :> Leave the > :> programming langauge at sh if it will eliminate an irrevlant complaint of > :> yours. > :Huh? Wtf is irrevlant? Can anyone understand that sentence? > It means irrelevant, Dan. Doesn't seem to me like a hard typo to > pattern-match out something that makes sense. But maybe your gifts > lie in other directions, like senseless attacks. Objective fact: You gave the first typo flame in this discussion. (``Data flaw,'' in case you've forgotten.) (I still don't understand that sentence, btw. The two halves don't seem connected in any way. I'll suppose for the sake of discussion that I have made some irrelevant complaint, though you haven't pointed out any such complaint. Why would leaving the programming language at sh eliminate a complaint of mine? I've been using csh throughout this subthread.) ---Dan
bill@bilver.uucp (Bill Vermillion) (01/30/91)
In article <2186:Jan2620:04:0191@kramden.acf.nyu.edu-> brnstnd@kramden.acf.nyu.edu (Dan Bernstein) writes: ->In article <1991Jan26.093659.26192@convex.com> tchrist@convex.COM (Tom Christiansen) writes: ->> How much mud can the mud-slinger sling? How many insults can be lobbed by ->> this sadly disturbed individual? Dragging in corporate affiliation like ->> this name is but another childish tactic, and it's not even close to ->> correct. ->Objective facts: Every nasty technique you accuse me of using, you used ->first. You started flaming first, you started insulting first, you ->started dragging in affiliation first. Any reader can verify these ->firsts. Why don't you guys take this flame war to email or at least to alt.flame? -- Bill Vermillion - UUCP: uunet!tarpit!bilver!bill : bill@bilver.UUCP