In Bash, to do a negative file globbing I have the following 2 choices. Is there a difference between them ? Both return the same result :
$ ls f1.txt f2.txt f3.txt f4.txt $ ls f[!24]* f1.txt f3.txt $ ls f[^24]* f1.txt f3.txt The [!...] pattern matches a single character that is not part of the ... set within the square brackets. This is a filename globbing pattern used by POSIX shells.
The [^...] pattern works the same, but is a POSIX regular expression. This pattern is not generally portable to other shells as a filename globbing pattern, but the bash shell recognizes it and treats it as identical to the [!...] pattern.
If you have a choice to choose between these two when writing a filename globbing pattern, you should most probably use the portable POSIX variant [!...].
The POSIX standard says about the filename globbing pattern [...] in general:
If an open bracket introduces a bracket expression as in XBD RE Bracket Expression, except that the
<exclamation-mark>character (!) shall replace the<circumflex>character (^) in its role in a non-matching list in the regular expression notation, it shall introduce a pattern bracket expression. A bracket expression starting with an unquoted<circumflex>character produces unspecified results. Otherwise,[shall match the character itself.
The "XBD RE Bracket Expression" thing is the specification for [...] in regular expressions.
The standard leaves the use of [^...] in a filename globbing pattern "unspecified" and the bash shell (and a few others) have chosen to implement this as identical to [!...].
[!x] instead of [^x] is that ^ was a pipe operator in the Thompson/Bourne shell. It's ^ in regexps and about every other shell (except some direct Bourne descendants like ksh88). In csh, and interactive bash, zsh, ! is a history expansion operator so [^x] is preferred there even though [!x] is supported in zsh/bash (though conflicts with history expansion). In rc / es, ^ is some form of concatenation operator, it's [~x] there for negation. fish doesn't support bracket expressions. ^ (which looked more like a ↑ at the time) was a pipe operator in the Thompson shell, but globbing was done with the /etc/glob helper (which gave their name to globs), and didn't support negation inside [...]. [!...] was likely introduced by the Bourne shell (which used | as pipe operator but kept ^ as well for backward compatibility).