bug-bash
[Top][All Lists]
Advanced

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

Re: Setting nullglob causes variables containing backslashes to be expan


From: Robert Elz
Subject: Re: Setting nullglob causes variables containing backslashes to be expanded to an empty string
Date: Wed, 07 Aug 2019 03:40:07 +0700

    Date:        Tue, 6 Aug 2019 16:00:21 -0400
    From:        Greg Wooledge <address@hidden>
    Message-ID:  <address@hidden>

  | Unquoted $a is a bad idea, which
  | may explain why it didn't receive enough testing to uncover whatever
  | this is.

A sane person might do it if
        a=foo*.c
and the objective was to list .c files starting with foo (this is
quite apart from the question of whether printf of echo is better to use).

In the case in question however, I agree, quoting should be used.

But I don't think there is any "lack of testing", rather this is operating
as it was designed to work,  it is just an incorrect design.

The point is that (unquoted) pathname expansion happens.  In pathname
expansion, \ is an escape character - but bash is treating that as if
it were a meta char, and actually performing pathname expansion.

Since (evidently from the reported behaviour) there isn't a "x30" file
in $PWD for the "pattern" to match, and nullglob is set, nothing is returned.

That is what you would expect to happen in those circonstances if we
had had
        a='foo*'
and there are no files with names starting with foo (and is also why
nullglob is a poor idea).

If we were to take this to its logical conclusion, with nullglob set

        echo foo

would do nothing, unless there is a file named "echo" in the current
directory (otherwise pathname expansion of echo would produce nothing)
and only write a newline if ./echo exists and "foo" does not. (nb: ./echo
isn't the command run, regular $PATH aand/or builtin or function lookups
are used - after the word expansion produces "foo")

Similarly

        ls -l

wold be an empty command unless "ls" and "-l" exist in $PWD, and we'd
always need to write "ls" "-l" to prevent pathname expansion happening.

(Of course if nullglob is disabled, none of this matters, as when the
pathname lookup fails to find anything, the original pattern uis used
as the word, which is what we want).

However, shells only attempt pathname expansion when the word contains
a glob metachar - which are '*' '?' and '['.  '\' is not one, or shouldn't
be, but bash was modified to treat it as if it were.   Rather, when pathname
expansion is being performed because of a meta-char in the word (words
containing /'s are more complex, so let's avoid that case here) then the
'\' is used as an escape characterso

        a='\**.c'; echo $a

should output the names of all files with names starting '*' and ending .c
(which can also be done using a='[*]*.c' but that method is less understood.

kre




reply via email to

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