user2365114
user2365114

Reputation: 43

BASH extglob negate not working as I expect

Suppose I have the following dir structure

./testdir
./testdir/a.c
./testdir/b.c
./testdir/testdir2/
./testdir/t.tar

and suppose my CWD is testdir and I want to echo all directory entries that don't have a .tar extension.

This works:

echo *.!(tar)

However, I expected this to produce the same result but it does not:

echo *!(tar)

Only the period is missing from the 2nd command. That 2nd echo command lists the d.tar file. The asterisk glob character should match all characters and the extglob negate should list anything that does not end with tar.

Upvotes: 1

Views: 853

Answers (2)

Etan Reisner
Etan Reisner

Reputation: 80931

The * and !(tar) bits aren't complementary globbed sets that are intersected.

They form a single glob that must expand.

I'm guessing t.tar matches for something like t.tar matches * and "" matches !(tar).

The glob you want is !(*tar). Anything that doesn't match the *tar glob.

Upvotes: 2

John1024
John1024

Reputation: 113864

Let's start with these files:

$ ls
a.b  b.c  testdir2  t.tar

This matches all files that have a period but do not have tar following the period:

$ echo *.!(tar)
a.b b.c

This matches all files that do not end with tar:

$ echo !(*tar)
a.b b.c testdir2

This is the extglob that surprises but shouldn't:

$ echo *!(tar)
a.b b.c testdir2 t.tar

The * itself can match anything, such as t.tar. Since it is not necessary to add tar after t.tar, this is a match.

Upvotes: 4

Related Questions