bug-bash
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Assignment of $* to a var removes spaces on unset IFS.


From: Greg Wooledge
Subject: Re: Assignment of $* to a var removes spaces on unset IFS.
Date: Wed, 15 Aug 2018 08:44:55 -0400
User-agent: NeoMutt/20170113 (1.7.2)

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 address@hidden

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.



reply via email to

[Prev in Thread] Current Thread [Next in Thread]