This reply was sent to me without Cc-ing the list. I have added the Cc. On Tue, Aug 14, 2018 at 11:39:20PM -0400, Bize Ma wrote: > On Tue, 14 Aug 2018 12:34:31, Greg Wooledge said: > > > I will also repeat, once more, my advice that one should NEVER write > > a script containing an unquoted $* or $@ expansion. > > That is plainly INCORRECT, Greg.
You are incorrect. > > It breaks in all kinds of ways in more than one shell. > > That several shells do different things is a bug on those shells, not bash. Agreed. And the fact that IN REAL LIFE, THOSE SHELLS EXIST AND HAVE THOSE BUGS, which are triggered by incorrect code, is a reason to write code correctly so as not to trigger those bugs. Or maybe you're one of those people who doesn't care about reality. > > Just don't do it, and these problems go away. > > If I want the split+glob to take effect I can do: > > echo $* > > > There is nothing wrong with that (don't claim that it change in different > shells, that is a different issue than using split+glob in bash, go back to > the point above about other shells if you wish). There is absolutely definitely positively 100% certainly something wrong with that. Let's break your script, shall we? Here's your script, except I'm going to represent it as a function. Doing it as a script would have the same effect. glob() { # "Return" (write to stdout, one per line) the expansions of all # arguments as globs against the current working directory. printf %s\\n $* } Will you at least agree that this is your intent, and a fair representation of your proposed solution? I'll take that as a "yes". So now, you can pass SOME globs to it (properly quoted), and it will appear to work for those globs: wooledg:~$ glob '*.pdf' 0400_0001.pdf 11412687.pdf 11412859.pdf [...] Epic Web Service - PatientLookup.pdf [...] At this point, the naive script writer will say "Yay, it worked!" The experienced script writer knows that it did not, in fact, "work". It only "worked" for this one degenerate kindergarten-level example. Let's test it again. wooledg:~$ glob '*Web Service*' *Web Service* But... but... but... the PREVIOUS glob worked! Why didn't this one work? Because the script (function) does not ACTUALLY work. It is broken. You can't solve this problem using an unquoted $* expansion. Not in reality. Some of us care about reality. Other languages have no problem with this. Tcl, for example, has a [glob] command that takes a list of glob-patterns and returns a list of files that match them. wooledg:~$ tclsh % puts [join [glob {*Web Service*}] \n] Epic Web Service - PatientLookup.pdf % puts [join [glob *.pdf] \n] Infoblox_DNS_mgmt.pdf prtest.pdf PMCNoteCoverPage.pdf [...] Of course, it doesn't sort them, because I didn't call [lsort]. Adding that is trivial. Now, you tried to implement Tcl's [glob] in bash, but you did it naively and the naive version does not work. You took a shortcut. That shortcut falls off a cliff. I'll leave the non-broken implementation as an exercise for the reader. Now, back to the original points: 1) Certain shells have bugs in them. These shells are in widespread use on real systems in real life. 2) One of those shells is bash, which makes it relevant to bug-bash. 3) Some of those bugs involve the unquoted expansions of $* and $@. 4) Even in the ABSENCE of such bugs, the use of an unquoted $* or $@ expansion does not actually solve the problems you claim it solves. 5) Therefore, for TWO reasons, you should not use unquoted $* or $@ in your shell scripts. Reason 1: it doesn't solve the problem. Reason 2: it sometimes breaks even worse due to shell bugs.