Unix & Linux Asked on November 21, 2021
Bash doesn’t perform word splitting in globbing in these cases:
var=$value # simple variable
declare -A hash
key="key with a space"
hash[$key]=$value # index of an associative array
arr=$(echo "1 2 3") # word splitting does happen here
[[ ]]
var="one two"
if [[ $var = *" "* ]]; then ... # check if var has a space in it
if [[ $(echo "one two") = $var ]]; then # use the output of command substitution to compare with var
(( ))
((sum = $(echo "99 + 1"))) # assigns 100 to sum
cat <<< * # gives '*' as the output
Is there a definite list of cases where Bash does or doesn’t perform word splitting and globbing?
That's typically the cases where it can't or it wouldn't make sense, so the non-list contexts. There are however non-list contexts where it does it, but complains when it results in more than one item, or joins those items with spaces.
Also, it's important to make the distinction between just wildcard pattern matching and filename generation or globbing, which is the generation of a list of file names that match a pattern.
For instance in [[ foo = * ]]
, there is no globbing, as in that *
is not expanded to the list of non-hidden files in the current directory, but that *
is still interpreted as a pattern (here it returns true as foo
matches the *
pattern).
By splitting here, we're referring to the implicit splitting that is done upon unquoted parameter expansion ($param
), command substitution ($(...)
and `...`
), and arithmetic expansion ($((...))
and $[...]
), using the $IFS
special parameter in list contexts.
We'll take *
as an example below. As a pattern, it matches any sequence of characters. As a glob it expands to all the non-hidden files in the current directory (subject to dotglob
, GLOBIGNORE
...).
The below applies to bash
, there are variations in other shells.
when quoted (with '*'
, "*"
, *
, $'*'
, $"*"
).
inside here documents (whether the delimiter is quoted or not):
cat << EOF
*
EOF
cat << 'EOF'
*
EOF
inside arithmetic expressions:
echo $((2 * 2))
(*
is not globbed but $((...))
undergoes split+glob, try after IFS=4
)array[2 * 2]=4
/ ${array[2 * 2]}
/ exec {array[2*2]}>&1
. Beware that you need the quotes in unset -v 'a[1]'
([1]
is a wildcard).((2 * 2))
echo $[2 * 2]
scalar variable assignment:
var=*
array[x]=*
hash[key]=*
array=([1]=*)
(older versions of bash
used to do globbing there though and do something different when there was a file called 1=foo
in the current directory for instance).var+=*
in associative array keys:
typeset -A hash; hash[**]=value; v=${hash[**]}
. *
and @
are special though.in assignments after export
/local
/typeset
/declare
/readonly
under some circumstances only: the assignment keyword and the variable name and =
must not be quoted even in part, and not be the result of any expansion. assignments and redirections may occurs before, but command
can't be used.:
export a=*
x=1 < /dev/null export foo a=*
""export a=*
command export a=*
export "a"=*
export a=*
"$(echo export)" a=*
more on that at Are quotes needed for local variable assignment?
case * in (...); esac
case x in (*); esac
(no split+glob, but that *
is treated as a pattern, that also applies to wildcard found inside unquoted expansions as in var=*; case x in ($var)
).
inside [[...]]
. Though note that pattern matching is done if unquoted wildcards are present on the right hand side of =
, ==
, !=
operators there.
in here strings since version 4.4. In earlier versions, splitting (though not globbing) was done and the resulting words joined with spaces.
in the target of redirections when the shell is in POSIX mode and non-interactive: bash -o posix -c 'echo test > *
. Otherwise, split+glob will be performed and bash
will report an error if that expanded to a list with less or more than 1 element.
Answered by Stéphane Chazelas on November 21, 2021
Get help from others!
Recent Answers
Recent Questions
© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP