[PATCH v2 3/8] lib/glob: accept [^...] as character class negation syntax

Josh Law posted 8 patches 3 weeks, 1 day ago
There is a newer version of this series
[PATCH v2 3/8] lib/glob: accept [^...] as character class negation syntax
Posted by Josh Law 3 weeks, 1 day ago
glob(7) specifies [!...] for negated character classes, but many
users are more familiar with the regex-style [^...] syntax.  Tools
like git, rsync, and bash all accept both forms, and the difference
is a common source of confusion when writing glob patterns.

Accept '^' as an alias for '!' at the start of a character class so
that both [!a-z] and [^a-z] work as expected.

Signed-off-by: Josh Law <objecting@objecting.org>
---
 lib/glob.c | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/lib/glob.c b/lib/glob.c
index df7f00619b1b..c5508be0d215 100644
--- a/lib/glob.c
+++ b/lib/glob.c
@@ -33,9 +33,9 @@ MODULE_LICENSE("Dual MIT/GPL");
  * Like !fnmatch(@pat, @str, 0) and unlike the shell, this does NOT
  * treat / or leading . specially; it isn't actually used for pathnames.
  *
- * Note that according to glob(7) (and unlike bash), character classes
- * are complemented by a leading !; this does not support the regex-style
- * [^a-z] syntax.
+ * Note that according to glob(7), character classes are complemented by
+ * a leading !.  The regex-style [^a-z] syntax is also accepted as an
+ * alias.
  *
  * An opening bracket without a matching close is matched literally.
  */
@@ -72,7 +72,7 @@ bool __pure glob_match(char const *pat, char const *str)
 		case '[': {	/* Character class */
 			if (c == '\0')	/* No possible match */
 				return false;
-			bool match = false, inverted = (*pat == '!');
+			bool match = false, inverted = (*pat == '!' || *pat == '^');
 			char const *class = inverted ? pat + 1 : pat;
 			unsigned char a = *class++;
 
-- 
2.34.1