From 63ffa8e950de5d25f32464b31885e5363c55e8cc Mon Sep 17 00:00:00 2001 From: Paul Eggert Date: Tue, 6 May 2025 05:04:04 -0700 Subject: [PATCH] More shell patterns to avoid * doc/autoconf.texi (Shell Pattern Matching): Improve on the recent discussion about brace expansion. --- doc/autoconf.texi | 55 ++++++++++++++++++++++++++++++++++++----------- 1 file changed, 42 insertions(+), 13 deletions(-) diff --git a/doc/autoconf.texi b/doc/autoconf.texi index 129e80181..127344467 100644 --- a/doc/autoconf.texi +++ b/doc/autoconf.texi @@ -16272,25 +16272,54 @@ File names are case insensitive, so even names like @section Shell Pattern Matching @cindex Shell pattern matching -Nowadays portable patterns can use negated character classes like -@samp{[!-aeiou]}. The older syntax @samp{[^-aeiou]} is supported by -some shells but not others; hence portable scripts should never use -@samp{^} as the first character of a bracket pattern. +Portable patterns should avoid the following constructs: -Outside the C locale, patterns like @samp{[a-z]} are problematic since -they may match characters that are not lower-case letters. +@itemize @bullet +@item +A bracket expression like @samp{[a-z]} outside the C locale. +This pattern may match characters that are not lower-case letters. +Outside the C locale, use @samp{[[:lower:]]} instead, +or to match just lower-case ASCII letters use +@samp{[abcdefghijklmnopqrstuvwxyz]}. + +@item +A bracket expression starting with @samp{^}. +For example, @samp{[!-aeiou]} is portable, but @samp{[^-aeiou]} is not. -Patterns with braces are, although not specified by POSIX, supported -by most shells. Not so by AIX 7.3 @command{/bin/sh}, though: +@item +When matching file names, a pattern containing @samp{*}, @samp{?} or +@samp{[...]} that might match the file names @samp{.} or @samp{..}. +For example @samp{.*} might match @samp{.} and @samp{..}, but it might not. + +@item +Any of the following characters, +unless quoted or escaped or in a bracket expression: @example -$ @kbd{ls -1 sequence000.c sequence999.c} -sequence000.c -sequence999.c -$ @kbd{ls -1 sequence@{000,999@}.c} -ls: 0653-341 The file sequence@{000,999@}.c does not exist. +! # % = [ ] ^ @{ @} ~ @end example +An unescaped @samp{[} that does not introduce a bracket expression is +problematic because, for example, @samp{a*[} might match the file name +@samp{abc[}, but it might not. + +Curly braces are problematic because POSIX allows but does not require +brace expansion. For example, the shell command @samp{echo a@{b,c,d@}e} +outputs @samp{abe ace ade} with Bash, but @samp{a@{b,c,d@}e} with Dash. + +@item +Backlashes in bracket expressions, unless doubled. +For example, @samp{[\\^]} is portable, but @samp{[\^]} is not. + +@item +An unescaped backslash at pattern end. + +@item +A NUL byte. +More generally, a NUL byte should never appear anywhere +in a portable shell script. +@end itemize + @node Shell Substitutions @section Shell Substitutions @cindex Shell substitutions -- 2.47.3