mirror of
https://https.git.savannah.gnu.org/git/bash.git
synced 2026-06-27 07:43:07 +02:00
new shell option to force globbing never to return .' and ..' as matches
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
+7
-2
@@ -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 */
|
||||
|
||||
@@ -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)
|
||||
|
||||
+21
-3
@@ -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.
|
||||
|
||||
@@ -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.
|
||||
|
||||
+2
-2
@@ -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
|
||||
|
||||
+1
-1
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
+16
-6
@@ -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=()
|
||||
|
||||
@@ -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
|
||||
|
||||
+1
-1
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
+14
-14
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
+5
-1
@@ -121,6 +121,10 @@ a\*b
|
||||
a\*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*>
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user