3

I've learned that the shell expands certain kinds of characters. That's why when writing:

$ echo *

I get a list of directories and files, let's say I get:

Applications Desktop Documents

now, Let's say I write

$ foo=Applications Desktop Documents

I get:

-bash: Desktop: command not found

Good, But when writing:

$ foo=*

That works, why? I was sure that * should expand and give the same error as above.

When writing

$ echo ${#foo}

I get the answer 1, which reveals that * is saved to foo

Why wasn't * expanded in the assignment? It does expand when I write

$ echo ${foo}

Thanks

3

Pathname expansion does not occur during a variable assignment. Here is an excerpt from the bash manpage:

If value is not given, the variable is assigned the null string. All values undergo tilde expansion, parameter and variable expansion, command substitution, arithmetic expansion, and quote removal (see EXPANSION below). If the variable has its integer attribute set, then value is evaluated as an arithmetic expression even if the $((...)) expansion is not used (see Arithmetic Expansion below). Word splitting is not performed, with the exception of "$@" as explained below under Special Parameters. Pathname expansion is not performed.

When you perform the assignment of foo=*, the foo variable will contain a literal *. When you later use the variable (unquoted) the parameter first expands to the literal * and then pathname expansion occurs. You can verify that it contains a literal * by quoting the parameter expansion:

$ foo=*
$ echo "$foo"
*

There are some exceptions to this rule in bash, such as when assigning an array:

$ foo=(*)

In the above example, pathname expansion happens immediately and the array contains a list of files matching the glob.

0

If a wildcard cannot expand into a glob by the shell, it is treated literally:

$ cd scratch
$ rm *
$ foo=*
$ echo $foo
*
$ echo "$foo"
*
$ touch file
$ echo $foo
file
$ echo "$foo"
*
  • While that's true, that's not exactly what's going on in his example. That behavior can also be changed in bash by setting nullglob. – jordanm Nov 30 '18 at 16:25

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.