Date: Tue, 6 Aug 2019 16:00:21 -0400 From: Greg Wooledge <wool...@eeg.ccf.org> Message-ID: <20190806200021.gk1...@eeg.ccf.org>
| 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