Reputation: 3683
I found this sudo wrapper from Zsh mailing list:
alias sudo='noglob do_sudo '
function do_sudo
{
integer glob=1
local -a run
run=( command sudo )
if [[ $# -gt 1 && $1 = -u ]]; then
run+=($1 $2)
shift ; shift
fi
(($# == 0)) && 1=/bin/zsh
while (($#)); do
case "$1" in
command|exec|-) shift; break ;;
nocorrect) shift ;;
noglob) glob=0; shift ;;
*) break ;;
esac
done
if ((glob)); then
PATH="/sbin:/usr/sbin:/usr/local/sbin:$PATH" $run $~==*
else
PATH="/sbin:/usr/sbin:/usr/local/sbin:$PATH" $run $==*
fi
}
It uses $~==*
to expand the file patterns. What is this kind of expansion called? Where is it documented? (really have got no idea how to search for this, 'dollar tilde expansion', 'filename expansion', 'tilde expansion' all just gave me some irrelevant results...)
And I noticed that actually $~var
also works, e.g.
$ touch foo bar
$ t1='fo*'
$ echo $~t1
foo
$ t2=('fo*' 'ba*')
$ echo $~t2
foo bar
Is it any different from $~==t1
? Btw it seems there can be an arbitrary number of =
s between $
and variable name, $~=t1
$=~t1
$~=====t1
all look the same.
Upvotes: 2
Views: 622
Reputation: 3683
Thanks to @chepner for the hint. Here's what I found in zshexpn
manual:
${=spec}
Perform word splitting using the rules for SH_WORD_SPLIT during the evaluation of spec, but regardless of whether the parameter appears in double quotes; if the `=' is
doubled, turn it off. This forces parameter expansions to be split into separate words before substitution, using IFS as a delimiter. This is done by default in most
other shells.
Note that splitting is applied to word in the assignment forms of spec before the assignment to name is performed. This affects the result of array assignments with the A
flag.
${~spec}
Turn on the GLOB_SUBST option for the evaluation of spec; if the `~' is doubled, turn it off. When this option is set, the string resulting from the expansion will be in‐
terpreted as a pattern anywhere that is possible, such as in filename expansion and filename generation and pattern-matching contexts like the right hand side of the `='
and `!=' operators in conditions.
In nested substitutions, note that the effect of the ~ applies to the result of the current level of substitution. A surrounding pattern operation on the result may can‐
cel it. Hence, for example, if the parameter foo is set to *, ${~foo//\*/*.c} is substituted by the pattern *.c, which may be expanded by filename generation, but
${${~foo}//\*/*.c} substitutes to the string *.c, which will not be further expanded.
So ~
enables globbing which substitutes patterns (specs) with file names. ==
makes sure that word splitting is disabled for strings in quotes.
For example:
$ touch foo bar
$ spec='fo* ba*'
$ echo $~spec
zsh: no matches found: fo* ba*
$ echo $~=spec
foo bar
$ echo $~==spec
zsh: no matches found: fo* ba*
$ function test1() { printf '1=%s 2=%s\n' $1 $2; }
$ test1 $spec
1=fo* ba* 2=
$ test1 $~spec
zsh: no matches found: fo* ba*
$ test1 $~=spec
1=foo 2=bar
$ test1 $~==spec
zsh: no matches found: fo* ba*
$ test1 $=spec
1=fo* 2=ba*
Upvotes: 2