]> git.ipfire.org Git - thirdparty/bash.git/commitdiff
new shell option to force globbing never to return `.' and `..' as matches
authorChet Ramey <chet.ramey@case.edu>
Tue, 4 Jan 2022 15:11:48 +0000 (10:11 -0500)
committerChet Ramey <chet.ramey@case.edu>
Tue, 4 Jan 2022 15:11:48 +0000 (10:11 -0500)
21 files changed:
CWRU/CWRU.chlog
MANIFEST
arrayfunc.c
builtins/shopt.def
doc/bash.1
doc/bashref.texi
doc/version.texi
execute_cmd.c
lib/glob/glob.c
subst.c
tests/assoc.right
tests/assoc.tests
tests/assoc11.sub
tests/assoc14.sub
tests/assoc17.sub [new file with mode: 0644]
tests/extglob.right
tests/extglob7.sub
tests/glob.right
tests/glob.tests
tests/glob10.sub [new file with mode: 0644]
tests/shopt.right

index fe24b64173085e973e51f689181b4446aec6b026..158376f5d10d7c8eee24b0d761cec1947347ba05 100644 (file)
@@ -2788,4 +2788,30 @@ builtins/common.c
        - INTERNAL_DEBUG: use instead of calls to itrace protected by #ifdef
          DEBUG
 
+                                  12/26
+                                  -----
+lib/glob/glob.c
+       - glob_always_skip_dot_and_dotdot: initialize to 1 (enabled)
+
+builtins/shopt.def
+       - globskipdots: new shell option, exposes glob_always_skip_dot_and_dotdot
 
+doc/{bash.1,bashref.texi}
+       - globskipdots: document new shell option
+
+execute_cmd.c
+       - fix_arrayref_words: call valid_array_reference with 0 for third arg
+         because the words have not undergone any word expansions yet and
+         the quotes are still present. This makes things like
+               A=[\[]=set
+               unset A[\[]
+         work
+
+subst.c
+       - word_list_split: if a word undergoes word splitting but is not
+         changed, preserve any W_ARRAYREF flag into the new word. This makes
+         things like
+               rkey=']'
+               unset A[$rkey]
+         work because the unset builtin sees the W_ARRAYREF flag on its
+         argument
index 2111707170c5f7b25aac7382427f67f4b18c9ac9..1e326eefd4ea98929d9a39819caa8102c24a33a3 100644 (file)
--- a/MANIFEST
+++ b/MANIFEST
@@ -954,6 +954,7 @@ tests/assoc13.sub   f
 tests/assoc14.sub      f
 tests/assoc15.sub      f
 tests/assoc16.sub      f
+tests/assoc17.sub      f
 tests/attr.tests       f
 tests/attr.right       f
 tests/attr1.sub                f
@@ -1144,6 +1145,7 @@ tests/glob6.sub           f
 tests/glob7.sub                f
 tests/glob8.sub                f
 tests/glob9.sub                f
+tests/glob10.sub       f
 tests/glob.right       f
 tests/globstar.tests   f
 tests/globstar.right   f
index 11b03ca96119c945408a8ed42530b9eb77154992..1f9b84fdf2953fa112f9cb9283863241c94cf670 100644 (file)
@@ -1255,7 +1255,7 @@ tokenize_array_reference (name, flags, subp)
      char **subp;
 {
   char *t;
-  int r, len, isassoc;
+  int r, len, isassoc, ssflags;
   SHELL_VAR *entry;
 
   t = mbschr (name, '[');      /* ] */
@@ -1270,10 +1270,15 @@ tokenize_array_reference (name, flags, subp)
       if (r == 0)
        return 0;
 
+      ssflags = 0;
       if (isassoc && ((flags & (VA_NOEXPAND|VA_ONEWORD)) == (VA_NOEXPAND|VA_ONEWORD)))
        len = strlen (t) - 1;
       else if (isassoc)
-       len = skipsubscript (t, 0, flags&VA_NOEXPAND);  /* VA_NOEXPAND must be 1 */
+       {
+         if (flags & VA_NOEXPAND)
+           ssflags |= 1;
+         len = skipsubscript (t, 0, ssflags);
+       }
       else
        /* Check for a properly-terminated non-null subscript. */
        len = skipsubscript (t, 0, 0);          /* arithmetic expression */
index 1c78260117f05364afe10eadb56233dbd887ccfd..52204c7bfc1fdd47018af2c4e772ad705975c71b 100644 (file)
@@ -89,6 +89,7 @@ extern int check_jobs_at_exit;
 extern int autocd;
 extern int glob_star;
 extern int glob_asciirange;
+extern int glob_always_skip_dot_and_dotdot;
 extern int lastpipe_opt;
 extern int inherit_errexit;
 extern int localvar_inherit;
@@ -210,6 +211,7 @@ static struct {
   { "force_fignore", &force_fignore, (shopt_set_func_t *)NULL },
 #endif
   { "globasciiranges", &glob_asciirange, (shopt_set_func_t *)NULL },
+  { "globskipdots", &glob_always_skip_dot_and_dotdot, (shopt_set_func_t *)NULL },
   { "globstar", &glob_star, (shopt_set_func_t *)NULL },
   { "gnu_errfmt", &gnu_error_format, (shopt_set_func_t *)NULL },
 #if defined (HISTORY)
index 34a01f468f36bbded291915aeda0f2f69175e879..d35468da61836464441e17d4e3299c997aea8998 100644 (file)
@@ -5,12 +5,12 @@
 .\"    Case Western Reserve University
 .\"    chet.ramey@case.edu
 .\"
-.\"    Last Change: Mon Nov 22 09:58:49 EST 2021
+.\"    Last Change: Sun Dec 26 16:02:07 EST 2021
 .\"
 .\" bash_builtins, strip all but Built-Ins section
 .if \n(zZ=1 .ig zZ
 .if \n(zY=1 .ig zY
-.TH BASH 1 "2021 November 22" "GNU Bash 5.2"
+.TH BASH 1 "2021 December 26" "GNU Bash 5.2"
 .\"
 .\" There's some problem with having a `@'
 .\" in a tagged paragraph with the BSD man macros.
@@ -714,7 +714,7 @@ Expressions are composed of the primaries described below under
 .SM
 .BR "CONDITIONAL EXPRESSIONS" .
 The words between the \fB[[\fP and \fB]]\fP do not undergo word splitting
-and filename expansion.
+and pathname expansion.
 The shell performs tilde expansion, parameter and
 variable expansion, arithmetic expansion, command substitution, process
 substitution, and quote removal on those words
@@ -3742,6 +3742,14 @@ the pattern must begin with ``.'' (for example, ``.?''),
 even if
 .B dotglob
 is set.
+If the
+.B globskipdots
+shell option is enabled, the filenames
+.B ``.''
+and
+.BR ``..''
+are never matched, even if the pattern begins with a
+.BR ``.'' .
 When not matching pathnames, the
 .B ``.''
 character is not treated specially.
@@ -3759,6 +3767,7 @@ below under
 for a description of the
 .BR nocaseglob ,
 .BR nullglob ,
+.BR globskipdots ,
 .BR failglob ,
 and
 .B dotglob
@@ -10361,6 +10370,15 @@ and
 .BR B ,
 and upper-case and lower-case ASCII characters will collate together.
 .TP 8
+.B globskipdots
+If set, pathname expansion will never match the filenames
+.B ``.''
+and
+.BR ``..'' ,
+even if the pattern begins with a
+.BR ``.'' .
+This option is enabled by default.
+.TP 8
 .B globstar
 If set, the pattern \fB**\fP used in a pathname expansion context will
 match all files and zero or more directories and subdirectories.
index df64c302705288ca4dfb180a13143ec94cf606f5..fdfc50811dd1099c1f93b290a0e1d9b8bac309db 100644 (file)
@@ -2757,6 +2757,9 @@ must be matched explicitly, unless the shell option @code{dotglob} is set.
 In order to match the filenames @samp{.} and @samp{..},
 the pattern must begin with @samp{.} (for example, @samp{.?}),
 even if @code{dotglob} is set.
+If the @code{globskipdots} shell option is enabled, the filenames
+@samp{.} and @samp{..} are never matched, even if the pattern begins
+with a @samp{.}.
 When not matching filenames, the @samp{.} character is not treated specially.
 
 When matching a filename, the slash character must always be
@@ -2766,6 +2769,7 @@ below (@pxref{Pattern Matching}).
 
 See the description of @code{shopt} in @ref{The Shopt Builtin},
 for a description of the @code{nocaseglob}, @code{nullglob},
+@code{globskipdots},
 @code{failglob}, and @code{dotglob} options.
 
 The @env{GLOBIGNORE}
@@ -5692,6 +5696,12 @@ is not taken into account, so
 @samp{b} will not collate between @samp{A} and @samp{B},
 and upper-case and lower-case ASCII characters will collate together.   
 
+@item globskipdots
+If set, filename expansion will never match the filenames
+@samp{.} and @samp{..},
+even if the pattern begins with a @samp{.}.
+This option is enabled by default.
+
 @item globstar
 If set, the pattern @samp{**} used in a filename expansion context will
 match all files and zero or more directories and subdirectories.
index 248ea17d0a8e3e2946781c3c6a80ba0d012603b7..7fca4730a40b86bb894dc8df5907b77d242d08c2 100644 (file)
@@ -2,10 +2,10 @@
 Copyright (C) 1988-2021 Free Software Foundation, Inc.
 @end ignore
 
-@set LASTCHANGE Thu Dec  2 15:07:19 EST 2021
+@set LASTCHANGE Sun Dec 26 16:02:48 EST 2021
 
 @set EDITION 5.2
 @set VERSION 5.2
 
-@set UPDATED 2 December 2021
+@set UPDATED 26 December 2021
 @set UPDATED-MONTH December 2021
index b4f71b195845e9bcdbbbb81ab37be0cbe0da8a7c..f86f396ad6f8cc9eef83f0384d05f26785520c2d 100644 (file)
@@ -4268,7 +4268,7 @@ fix_arrayref_words (words)
 
   for (w = wcmd->next; w; w = w->next)
     {
-      if (w->word && w->word->word && valid_array_reference (w->word->word, VA_NOEXPAND))
+      if (w->word && w->word->word && valid_array_reference (w->word->word, 0))
        w->word->flags |= W_ARRAYREF;
     }
 }
index 5aa34794b4a11e9ef1d7570169695f70450be633..1a6515409babbc57e2273138759f5553a19357af 100644 (file)
@@ -103,7 +103,7 @@ int glob_ignore_case = 0;
 /* Global variable controlling whether globbing ever returns . or ..
    regardless of the pattern. If set to 1, no glob pattern will ever
    match `.' or `..'. Disabled by default. */
-int glob_always_skip_dot_and_dotdot = 0;
+int glob_always_skip_dot_and_dotdot = 1;
 
 /* Global variable to return to signify an error in globbing. */
 char *glob_error_return;
diff --git a/subst.c b/subst.c
index bf2a8d391a67a54f115373c5b9ae27db914a7862..72c61dc2b296085c8498f3028057521879575423 100644 (file)
--- a/subst.c
+++ b/subst.c
@@ -1819,7 +1819,7 @@ skip_matched_pair (string, start, open, close, flags)
                          : skip_double_quoted (ss, slen, ++i, 0);
          /* no increment, the skip functions increment past the closing quote. */
        }
-      else if ((flags&1) == 0 && c == '$' && (string[i+1] == LPAREN || string[i+1] == LBRACE))
+      else if ((flags & 1) == 0 && c == '$' && (string[i+1] == LPAREN || string[i+1] == LBRACE))
        {
          si = i + 2;
          if (string[si] == '\0')
@@ -11608,6 +11608,12 @@ word_list_split (list)
          w->word[0] = '\0';
          tresult = make_word_list (w, (WORD_LIST *)NULL);
        }
+#if defined (ARRAY_VARS)
+      /* pass W_ARRAYREF through for words that are not split and are
+        identical to the original word. */
+      if (tresult && tresult->next == 0 && t->next == 0 && (t->word->flags & W_ARRAYREF) && STREQ (t->word->word, tresult->word->word))
+       tresult->word->flags |= W_ARRAYREF;
+#endif
       if (result == 0)
         result = e = tresult;
       else
index 1d558228a2bd61a774db862570c798f8c9d2e4cb..3516a6e55aa6a7b41c890da729cf81f5363c85de 100644 (file)
@@ -253,12 +253,12 @@ declare -A dict=(["?"]="quest" ["*"]="star" ["'"]="squote" ["\$"]="dol" ["\""]="
 dict=( "?" "quest" "*" "star" "'" "squote" "\$" "dol" "\"" "dquote" "\\" "bslash" "@" "at" "}" "rbrace" "{" "lbrace" "\`" "bquote" )
 declare -A foo=([two]="" [one]="1" )
 foo=( two "" one "1" )
-rparen dquote rbrace bs
-declare -A a=([")"]="rparen" ["\""]="dquote" ["]"]="rbrace" ["\\"]="bs" )
-")" "rparen" "\"" "dquote" "]" "rbrace" "\\" "bs"
-declare -A a=([")"]="rparen" ["\""]="dquote" ["]"]="rbrace" ["\\"]="bs" )
-declare -A a=([")"]="rparen" ["\""]="dquote" ["]"]="rbrace" ["\\"]="bs" )
-declare -A a=([")"]="rparen" ["\""]="dquote" ["]"]="rbrace" ["\\"]="bs" )
+rparen dquote rbracket bs
+declare -A a=([")"]="rparen" ["\""]="dquote" ["]"]="rbracket" ["\\"]="bs" )
+")" "rparen" "\"" "dquote" "]" "rbracket" "\\" "bs"
+declare -A a=([")"]="rparen" ["\""]="dquote" ["]"]="rbracket" ["\\"]="bs" )
+declare -A a=([")"]="rparen" ["\""]="dquote" ["]"]="rbracket" ["\\"]="bs" )
+declare -A a=([")"]="rparen" ["\""]="dquote" ["]"]="rbracket" ["\\"]="bs" )
 declare -Arx foo=([two]="2" [three]="3" [one]="1" )
 ./assoc11.sub: line 90: foo: readonly variable
 declare -A v1=(["1 2"]="3" )
@@ -383,3 +383,13 @@ set
 stderr
 42
 42
+declare -A A=(["]"]="rbracket" ["["]="lbracket" )
+declare -A A=()
+declare -A A=(["]"]="rbracket" ["["]="lbracket" )
+declare -A A=()
+declare -A A=(["]"]="rbracket" ["["]="lbracket" )
+declare -A A=()
+declare -A A=(["]"]="rbracket" ["["]="lbracket" )
+declare -A A=()
+declare -A A=(["]"]="rbracket" ["["]="lbracket" )
+declare -A A=()
index 5dd90ce522ebff28a4b05212d3c047b0cc41994e..5fc2b2cff8012e946eff3d9b8787ec81774cc880 100644 (file)
@@ -259,3 +259,6 @@ ${THIS_SH} ./assoc15.sub
 
 # tests with subscripts being expanded more than one in ${xxx} word expansions
 ${THIS_SH} ./assoc16.sub
+
+# tests with `[' and `]' subscripts and `unset'
+${THIS_SH} ./assoc17.sub
index 13111a52b14a47ccdb275a9eb1ec309cba79dafd..9d9afae95e73c1294950ba37e42c09fe5c974329 100644 (file)
@@ -69,7 +69,7 @@ foo=(one 1 two)
 declare -p foo
 echo foo=\( ${foo[@]@K} \)
 
-typeset -A a=( [\\]=bs [\"]=dquote [\)]=rparen [\]]=rbrace )
+typeset -A a=( [\\]=bs [\"]=dquote [\)]=rparen [\]]=rbracket )
 echo ${a[@]}
 declare -p a
 
index 854878c027a2c91782f8d8479df4f84351a5afc8..95df04925e4dade556bdc1eec05b03ccb3167bb1 100644 (file)
@@ -1,3 +1,17 @@
+#   This program is free software: you can redistribute it and/or modify
+#   it under the terms of the GNU General Public License as published by
+#   the Free Software Foundation, either version 3 of the License, or
+#   (at your option) any later version.
+#
+#   This program is distributed in the hope that it will be useful,
+#   but WITHOUT ANY WARRANTY; without even the implied warranty of
+#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#   GNU General Public License for more details.
+#
+#   You should have received a copy of the GNU General Public License
+#   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+#
+
 declare -A assoc=(hello world "key with spaces" "value with spaces" one 1 foo bar)
 declare -p assoc
 
diff --git a/tests/assoc17.sub b/tests/assoc17.sub
new file mode 100644 (file)
index 0000000..a98aaa1
--- /dev/null
@@ -0,0 +1,58 @@
+#   This program is free software: you can redistribute it and/or modify
+#   it under the terms of the GNU General Public License as published by
+#   the Free Software Foundation, either version 3 of the License, or
+#   (at your option) any later version.
+#
+#   This program is distributed in the hope that it will be useful,
+#   but WITHOUT ANY WARRANTY; without even the implied warranty of
+#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#   GNU General Public License for more details.
+#
+#   You should have received a copy of the GNU General Public License
+#   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+#
+# test behavior with `unset' and `[' and ']' subscripts
+
+declare -A A
+rkey=']'
+lkey='['
+
+A[$rkey]=rbracket
+A[$lkey]=lbracket
+declare -p A
+
+unset A[$rkey]
+unset A[$lkey]
+declare -p A
+
+A["$rkey"]=rbracket
+A["$lkey"]=lbracket
+declare -p A
+
+unset A["$rkey"]
+unset A["$lkey"]
+declare -p A
+
+A[\]]=rbracket
+A[\[]=lbracket
+declare -p A
+
+unset A[\]]
+unset A[\[]
+declare -p A
+
+A[']']=rbracket
+A['[']=lbracket
+declare -p A
+
+unset A[']']
+unset A['[']
+declare -p A
+
+A["]"]=rbracket
+A["["]=lbracket
+declare -p A
+
+unset A["]"]
+unset A["["]
+declare -p A
index e8f954ac974f04151065b0170cd1121887f08138..2974cecaf8f974abcccada768528196a5e72440c 100644 (file)
@@ -92,16 +92,16 @@ a ab
 a ab
 a ab
 a
-. ..
-. .. a.log
+*(.)
+a.log
 *(foo)
 *(foo|bar)
 a.log
 ?(foo)
 a.log
 a.log
-. ..
-. ..
+*(foo).*
+*(foo|bar).*
 a.log
 a.log
 .x .y .z
@@ -114,16 +114,16 @@ a b c
 .x .y .z a b c
 .x .y .z a b c
 *
-.. .b a
-.. .b a
-a .. .b
-. .. .b
-. .. .b
-.. .b a
-.. .b a
-a .. .b
-. .. .b
-. .. .b
+.b a
+.b a
+a .b
+.b
+.b
+.b a
+.b a
+a .b
+.b
+.b
 dotglob: .a .foo bar
 @(.foo)
 .foo
index 07a6071b72cba17d9b6e4aa238b65edc462ba31b..5fab9cdabcadf24d166e5dca8561b5f0ec63cb07 100644 (file)
@@ -12,6 +12,7 @@ cd $TESTDIR || {
 
 LC_CTYPE=C LC_COLLATE=C
 shopt -s extglob dotglob
+shopt -u globskipdots          # XXX - backwards compatibility
 touch .foo bar .a
 
 echo dotglob: .a .foo bar
index 9496690502b1799eba1c5793eff058f01324e246..723ee7b466b991608b69595f8ca592f646695600 100644 (file)
@@ -121,6 +121,10 @@ a\*b
 a\\ 1*b*
 é/*
 é/*
+a aa b bb
+.a .aa .b .bb a aa b bb
+.a .aa .b .bb
+. .. .a .aa .b .bb
 argv[1] = <a>
 argv[2] = <abc>
 argv[3] = <abd>
@@ -135,7 +139,7 @@ argv[2] = <abc>
 argv[3] = <abd>
 argv[4] = <abe>
 tmp/l1 tmp/l2 tmp/*4 tmp/l3
-./glob.tests: line 65: no match: tmp/*4
+./glob.tests: line 66: no match: tmp/*4
 argv[1] = <bdir/>
 argv[1] = <*>
 argv[1] = <a*>
index b35d7336ff693ecc871e00feaa7cb02b0551f611..02d530261513bca33d02a7beaceff36136132b2c 100644 (file)
@@ -30,6 +30,7 @@ ${THIS_SH} ./glob6.sub
 ${THIS_SH} ./glob7.sub
 ${THIS_SH} ./glob8.sub
 ${THIS_SH} ./glob9.sub
+${THIS_SH} ./glob10.sub
 
 MYDIR=$PWD     # save where we are
 
diff --git a/tests/glob10.sub b/tests/glob10.sub
new file mode 100644 (file)
index 0000000..7c14c0d
--- /dev/null
@@ -0,0 +1,32 @@
+#   This program is free software: you can redistribute it and/or modify
+#   it under the terms of the GNU General Public License as published by
+#   the Free Software Foundation, either version 3 of the License, or
+#   (at your option) any later version.
+#
+#   This program is distributed in the hope that it will be useful,
+#   but WITHOUT ANY WARRANTY; without even the implied warranty of
+#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#   GNU General Public License for more details.
+#
+#   You should have received a copy of the GNU General Public License
+#   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+#
+
+# test basic behavior of globskipdots
+TDIR=/tmp/dotglob-$$
+
+{ mkdir $TDIR && cd $TDIR; } || exit 1
+
+touch a b aa bb .a .b .aa .bb
+
+echo *
+shopt -s dotglob
+echo *
+
+shopt -s globskipdots
+echo .*
+shopt -u globskipdots
+echo .*
+
+cd $OLDPWD
+rm -rf $TDIR
index 177ea2f0999be44a38de44e15d32ab108e8b142c..d617c1d720c83cc9697dd2d82848348af67681bc 100644 (file)
@@ -28,6 +28,7 @@ shopt -s extquote
 shopt -u failglob
 shopt -s force_fignore
 shopt -s globasciiranges
+shopt -s globskipdots
 shopt -u globstar
 shopt -u gnu_errfmt
 shopt -u histappend
@@ -69,6 +70,7 @@ shopt -s expand_aliases
 shopt -s extquote
 shopt -s force_fignore
 shopt -s globasciiranges
+shopt -s globskipdots
 shopt -s hostcomplete
 shopt -s interactive_comments
 shopt -s patsub_replacement
@@ -302,5 +304,9 @@ xtrace              off
 --
 ./shopt.tests: line 106: shopt: xyz1: invalid shell option name
 ./shopt.tests: line 107: shopt: xyz1: invalid option name
+28c28
+< globskipdots         off
+---
+> globskipdots         on
 expand_aliases         on
 expand_aliases         on