ok@quintus.UUCP (Richard A. O'Keefe) (01/01/90)
Does anyone know why the C shell command "which" (ok, /usr/ucb/which) and the Bourne shell command "type" don't understand built-in commands? The manual page for csh says which [ filename ] ... which takes a list of names and looks for the files which would be executed had these names been given as commands. (Should be ^^^ "would have been", such grammar!) which makes it clear that "which if" isn't supposed to recognise "if" as a command. I don't quite see why; surely it would be easy for /usr/ucb/which to execute an appropriate switch() after everything else has failed. The manual page for sh says type [ name ... ] For each name, indicate how it would be interpreted if used as a command name. This certainly looks to me as though "type if" SHOULD succeed, and "type type" _does_. So why does "type while" say "while not found" rather than "while is a shell builtin"?
reschly@BRL.MIL (Robert J. Reschly Jr.) (01/02/90)
Richard, You say: > Does anyone know why the C shell command "which" (ok, /usr/ucb/which) > and the Bourne shell command "type" don't understand built-in commands? The "which" command is an independent program (actually a C-shell script) which can be called from any command interpreter. Since the various command interpreters offer differing sets of built-in commands, "which" cannot presume to know anything about built-in commands. Additionally there is no reasonable way for "which" to learn this information. > I don't quite see why; surely it would be easy for /usr/ucb/which to > execute an appropriate switch() after everything else has failed. Resulting in "which blurfle" responding with "blurfle is a shell built-in"? What action would you have the switch() branch take? Note that another failure mode for "which" involves using a shell other than /bin/csh while having a .cshrc in your home directory. If this .cshrc defines any aliases, "which" will gladly report them even though they are probably inappropriate. As for "type", I have no good answers. Given that "type type" reports itself as a shell built-in it should be able to report on other built-ins. My current shell of choice, "tcsh" handles this operation correctly. Later, Bob -------- Internet: reschly@BRL.MIL (or BRL.ARMY.MIL) Phone: (301)278-6808 AV: 298 UUCP: ...!{{cmcl2,nlm-mcs,husc6}!adm,smoke}!reschly Postal: Robert J. Reschly Jr. U.S. Army Ballistic Research Laboratory Systems Engineering and Concepts Analysis Division Networking and Systems Development Team ATTN: SLCBR-SE-A (Reschly) APG, MD 21005-5066 (Hey, *I* don't make 'em up!) **** For a good time, call: (303) 499-7111. Seriously! ****
tale@cs.rpi.edu (David C Lawrence) (01/02/90)
In article <21912@adm.BRL.MIL> reschly@BRL.MIL (Robert J. Reschly Jr.) writes: > Note that another failure mode for "which" involves using a shell > other than /bin/csh while having a .cshrc in your home directory. Not the only other failure mode, besides built-ins; it blows aliases too, even when you are using csh. Here's an article I wrote for a local group on this topic a month ago: ================ Newsgroups: rpi.suns Subject: Re: unaliasing Date: 30 Nov 89 08:31:54 GMT [Last update: Mon Jan 1 19:35:45 1990] [ This was written in reply to a reply of someone who asked this: I want to know the full path name of a command. The "which" command reads ~/.cshrc to check for alias, but I want the unaliased form of the command. Is there a way to do this without modifying the ~/.cshrc file? It was not an attempt to answer that question, but rather the one in the follow-up that wanted to know how come which screwed up so much.] Script started on Thu Nov 30 03:13:40 1989 bash$ which csh /bin/csh bash$ alias csh='echo foo' bash$ which csh /bin/csh bash$ alias alias csh="echo foo" bash$ csh foo bash$ type csh csh is aliased to `echo foo'. bash$ /bin/csh csh% which csh /bin/csh csh% alias csh 'echo foo' csh% which csh /bin/csh csh% csh foo csh% which statement no statement in /staff/cs/tale/bin /usr/local/gnu/bin /usr/bin/X11 /usr/local/bin /usr/etc /usr/bin /usr/ucb /bin /usr/5bin . csh% cat > .cshrc alias csh 'echo bar' alias alias statement 'which is stupid about a lot of things ...' csh% which statement statement: aliased to which is stupid about a lot of things ... csh% which csh csh: aliased to echo bar csh% csh foo csh% exit csh% bash$ exit script done on Thu Nov 30 03:16:06 1989 As has been pointed out, /usr/ucb/which reads your .cshrc to find out some information, usually aliases. It can get PATH from your environment; I haven't bothered checking which gets precedence if path information is in .cshrc. It was very much written for csh, even though it doesn't even work with it correctly. The problem is that which is a non-csh builtin attempting to get internal information from the programme. When using csh, the primary screw-ups are when you either have a) an alias defined interactively which does not exist in .cshrc or b) an alias mentioned in .cshrc which does not really exist in your current shell, as in the examples above. It does work correctly, however, for most csh users' normal environments. The "right way" is to have the function in the shell. Witness BASH's "type" builtin which gets it right for the cases where csh fails. ================ Dave [By the way, Robert, you might want to cut the length of your .signature by 60%+ to avoid some flames.] -- (setq mail '("tale@cs.rpi.edu" "tale@ai.mit.edu" "tale@rpitsmts.bitnet"))
ok@quintus.UUCP (Richard A. O'Keefe) (01/02/90)
In article <21912@adm.BRL.MIL> reschly@BRL.MIL (Robert J. Reschly Jr.) writes: >(I wrote): >> Does anyone know why the C shell command "which" (ok, /usr/ucb/which) >> and the Bourne shell command "type" don't understand built-in commands? > The "which" command is an independent program (actually a C-shell >script) which can be called from any command interpreter. Since the >various command interpreters offer differing sets of built-in commands, >"which" cannot presume to know anything about built-in commands. I'm afraid this reason is bogus. "which" expressly *DOES* recognise ***C*** shell aliases. It goes so far as to read your ~/.cshrc file just so that it can do this. For this reason it isn't any _use_ in anything other than the C shell. For example, % which cd cd: aliased to set old=$cwd; chdir !*; set-title-bar % sh -c "type cd" cd is a shell builtin What is more, "which" may not even use the same $PATH as the shell: % sh $ PATH=/usr/ucb:/bin:/usr/bin:/usr/local/bin $ type unde unde not found $ which unde /hughes/ok/commands.d/unde I think this clearly shows that any Bourne shell script which relies on 'which' is likely to get into serious trouble sooner or later. Given that it only makes sense to use 'which' from the C shell, where is the harm in having 'which' recognise C shell commands as well as C shell aliases?
chet@cwns1.CWRU.EDU (Chet Ramey) (01/03/90)
In article <1297@quintus.UUCP> ok@quintus.UUCP (Richard A. O'Keefe) writes: >The manual page for sh says > type [ name ... ] > For each name, indicate how it would be interpreted if > used as a command name. >This certainly looks to me as though "type if" SHOULD succeed, and >"type type" _does_. So why does "type while" say "while not found" >rather than "while is a shell builtin"? Because `while' is a sh language construct (a statement), not a shell builtin. It's a small but important distinction, and one of the chief reasons that programming in sh is so much better than programming in csh (in csh, these constructs *are* implemented as builtins, using very ad-hoc parsing with thousands of special cases that serves to reduce their usefulness to almost zero). -- Chet Ramey Network Services Group "Help! Help! I'm being Case Western Reserve University repressed!" chet@ins.CWRU.Edu
dce@smsc.sony.com (David Elliott) (01/03/90)
In article <21912@adm.BRL.MIL> reschly@BRL.MIL (Robert J. Reschly Jr.) writes: > The "which" command is an independent program (actually a C-shell >script) which can be called from any command interpreter. Since the >various command interpreters offer differing sets of built-in commands, >"which" cannot presume to know anything about built-in commands. >Additionally there is no reasonable way for "which" to learn this >information. Good try, but I don't think I can buy that, at least not as the only reason. You see, "which" will also look for aliases if you have a ~/.cshrc. If it was completely independent, it would at least look at SHELL to see if you are running sh or csh as your default shell, and with that info it could decide on a list of builtins to use. IMHO, the best way would be for each shell to have a builtin "what would I run if I gave this name" command, and Unix would have a "what's the pathname of this command" command, like the Tektronix systems have. -- David Elliott dce@smsc.sony.com | ...!{uunet,mips}!sonyusa!dce (408)944-4073 "But Pee Wee... I don't wanna be the baby!"
ok@quintus.UUCP (Richard A. O'Keefe) (01/03/90)
In article <1990Jan2.160927.11935@usenet.ins.cwru.edu> chet@po.CWRU.Edu writes: >In article <1297@quintus.UUCP> ok@quintus.UUCP (Richard A. O'Keefe) writes: >>...[in Bourne shell]... So why does "type while" say "while not found" >>rather than "while is a shell builtin"? >Because `while' is a sh language construct (a statement), not a shell >builtin. Yes, I *KNOW* that. That's an excellent argument for having "type while" say "while is a keyword" rather than "while is a shell builtin". It is *NOT* an argument for having "type while" say "while not found". Given the wording of the manual page, and a few seconds thought about what would be useful, it seems most natural to interpret the response "XXX not found" as meaning "a command cannot currently begin with the word XXX, so you can use XXX as the name of a new command without interfering with anything". That is, in fact, what I wanted to use 'type' and 'which' for. I often make up little shell scripts, and I get so tired of calling them all 'zabbo' and then forgetting what they do. I would like to put together a command "howabout X" which tells me if X is "free" in both the Bourne shell and the C shell, and the obvious way to do that is to check the output of both 'which $X' and 'sh -c "type $X"'. It looks as though the best I can do is to do that and then filter out keywords myself, which means that I have to adapt "howabout" myself for every UNIX system I deal with... Recommendation: it would be a Good Thing if "which X" said #Cshell builtin X # when X is a C-shell built-in command #Cshell keyword X # when X is part of a C-shell control structure and "type X" said X is a keyword # when X is part of a control structure so that no X in $PATH # which X not found # type would mean that X was not currently in use as the first word of a possible command.
randy@chinet.chi.il.us (Randy Suess) (01/04/90)
In article <1301@quintus.UUCP> ok@quintus.UUCP (Richard A. O'Keefe) writes: > >Yes, I *KNOW* that. That's an excellent argument for having "type while" >say "while is a keyword" rather than "while is a shell builtin". >It is *NOT* an argument for having "type while" say "while not found". (From within vi) r!type while while is a keyword r!type for for is a keyword This is with ksh version 88b on i386. -randy -- Randy Suess randy@chinet.chi.il.us
ruud@targon.UUCP (Ruud Harmsen) (01/04/90)
In article <1297@quintus.UUCP> ok@quintus.UUCP (Richard A. O'Keefe) writes: >Does anyone know why the C shell command "which" (ok, /usr/ucb/which) >and the Bourne shell command "type" don't understand built-in commands? > [stuff deleted] > >This certainly looks to me as though "type if" SHOULD succeed, and >"type type" _does_. So why does "type while" say "while not found" >rather than "while is a shell builtin"? The point is that "if", "while" etc. are keywords, i.e. lexical units that make the syntax of the shell command language. They do not do anything themselves, but rather control the way other things are done, or going to be done. "cd", "type" and (often) "test" etc. are commands that perform some action, and which happen to have been implemented without creating a separate process. (In the case of "cd", it has to be, in the other cases, speed is probably the only reason). So I would not object to type recognizing "while", but then as a keyword, not as a builtin *command*.
gwyn@smoke.BRL.MIL (Doug Gwyn) (01/05/90)
In article <1297@quintus.UUCP> ok@quintus.UUCP (Richard A. O'Keefe) writes: >This certainly looks to me as though "type if" SHOULD succeed, and >"type type" _does_. So why does "type while" say "while not found" >rather than "while is a shell builtin"? "while" is neither a command nor a builtin; it's a keyword in the shell programming language. "type" does have some deficiencies, which is why in the BRL Bourne shell we implemented the 8th Edition UNIX "whatis" and "builtin" commands.