21

I have been teaching myself the meaning of various bash 'reserved words'.

In doing this, I inadvertently typed the command

echo !()

To my surprise, this command executes, and produces output identical to the command

echo *

In other words, the output was a list of the contents of the current directory

file1 file2 directory1 directory2

Why is bash essentially expanding !() to * ?

I can't determine the meaning of (), as it seems to be an invalid expression in other contexts.

0

1 Answer 1

33

It's bash's extglob pattern matching syntax which it copied from the Korn shell (a subset thereof). !(pattern), when the extglob has been enabled one way or another (like via the bash_completion add-on in interactive shells) expands to the names of the (non-hidden by default) files in the current working directory that don't match pattern.

With an empty pattern, that's all files in the current directory whose name is not the empty string, but a file name cannot be empty anyway so that's all the (non-hidden by default) files.

You'll get the same in zsh with echo ^ when its extendedglob option is enabled where ^pattern is its equivalent of ksh's !(pattern).

1
  • 1
    Somewhat more usefully, e.g. foo!(*~) would give all files that start with foo, but do not end with a ~. Though one might try to use foo*!(~), which doesn't work since the * matches the ~, and the last !(~) only sees an empty string at the end, which it doesn't reject.
    – ilkkachu
    Commented Nov 8, 2023 at 7:36

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .