Path: utzoo!attcan!utgpu!jarvis.csri.toronto.edu!mailrus!csd4.milw.wisc.edu!cs.utexas.edu!uunet!auspex!guy From: guy@auspex.auspex.com (Guy Harris) Newsgroups: comp.unix.questions Subject: Re: Strangeness in shell Message-ID: <2277@auspex.auspex.com> Date: 24 Jul 89 18:38:02 GMT References: <432@mccc.UUCP> <9700009@osiris.cso.uiuc.edu> Reply-To: guy@auspex.auspex.com (Guy Harris) Organization: Auspex Systems, Santa Clara Lines: 84 > Ummm... I had always learned (obviously flawed) that the single quotes >prevented expansion of ANYTHING.... They do. That's why the statement x='*z' assigns the string "*z" to the variable "x". Note, though, that the string is "*z", not "'*z'" - in other words, the quotes are gone. (The quotes in "*z" in the statment ...assigns the string "*z" to the variable "x". mark the boundaries of the string; they are *not* part of the string. In other words, the variable "x" has a two-character string as its value, the first character of which is '*' and the second character of which is 'z'.) This means that the statement echo ${x} is expanded to echo *z by substituting the value of the variable "x" for the "${x}". *After* the substitution is performed, the command is cut up into tokens; the two tokens in this case are "echo" and "*z". Then the tokens have file-name expansion performed on them, so that "*z" expands either to a list of all the files whose names end with "z", if there are any such files, or to a list containing only "*z", if there aren't any such files. (All this is covered in the SH(1) man page in SunOS, and I think that's pretty much derived from the S5 man page, so it should be there as well. It takes a bit of searching to find the pieces of the description.) >Even if this is not the case, why does it behave differently in the two >cases? Because the "tokenization" is done between the variable expansion and the file name expansion. Thus, x='* z' assigns the three-character string "* z" to the variable "x", just as x='*z' assigned the two-character string "*z" to "x". The statement echo ${x} is then expanded into echo * z when the value of "x" is substituted into it. The quotes are not preserved, remember, so this is then broken into *three* tokens - "echo", "*", and "z". The first and third tokens expand to themselves when file-name expansion is performed; the second token expands to a list of all files in the current directory (except for those whose name begins with "."). Now if you want the "echo" to literally echo the value of "x", you should do echo "${x}" # or just echo "$x" because double-quotes prevent file-name expansion but do *not* prevent variable-name expansion. If you want "echo" to echo the string "${x}", rather than the value of the variable "x", do echo '${x}' >If you have no files ending in z , then why does it not return a null >string for the '*z' version ? Because that's the way the Bourne shell works. If a filename pattern doesn't match any file names, it is left unchanged, not expanded to a null string or a null list.