Within my ~./bashrc in an alias I have turned of globbing like this.
alias x='set -f;. any.sh'
But which command enables globbing again or should I set this options in any.sh?
Any response is welcome.
Within my ~./bashrc in an alias I have turned of globbing like this.
alias x='set -f;. any.sh'
But which command enables globbing again or should I set this options in any.sh?
Any response is welcome.
If you want globs to be disabled only while the shell is interpreting code in any.sh, with bash4.4+ or ash-based shells, you can do:
x() {
local -
set -o noglob
. any.sh
}
Or in zsh:
x() {
set -o localoptions -o noglob
. any.sh
}
That is use a function instead of an alias (you don't want to use aliases for several commands as that doesn't do what you want when you do cmd | x or cmd && x for instance), make sure changes to options (to the $- variable as one way to look at it) are local to the function, disable glob and source the file.
With older versions of bash, you could do:
x() {
local ret restore
[[ $- = *f* ]] || restore='set +o noglob'
set -o noglob
. any.sh
ret=$?
eval "$restore"
return "$ret"
}
Or maybe a more generic helper function like:
withopt() {
local ret option
local -a restore
option=$1; shift
[[ -o $option ]] || restore=(set +o "$option")
set -o "$option"
"$@"
ret=$?
"${restore[@]}"
return "$ret"
}
And then, you can use an alias if you like like:
alias x='withopt noglob . any.sh'
Note that it doesn't prevent * from being expanded if you do:
x *
As the noglob option ends up being enabled long after that command has been evaluated. For that, see my other answer (an answer to a different question).
This was posted before the question was clarified, and now addresses a different need. I'm still leaving it here as that can be useful to others.
I suppose you want to be able to do:
x *.txt
and the *.txt to be passed unexpanded to any.sh and globs to be reenabled afterwards.
You can't do that with bash. Use zsh instead where you can do:
alias x='noglob any.sh`
Where noglob disables aliases only for that command.
$ echo /etc/p*d
/etc/pam.d /etc/passwd /etc/profile.d
$ noglob echo /etc/p*d
/etc/p*d
Note that it affects the expansion of globs in arguments of that echo commands only. * would still be expanded in noglob echo $(echo *) or noglob eval 'echo *' or noglob . some-script where some-script does a echo *.
Actually, there may be a way with bash:
oneshot_noglob() {
case $- in
(*f*) ;; # globs already disabled
(*) set -f; shot=0; debug_trap=$(trap -p DEBUG)
trap '
if ((++shot == 2)); then
set +f
trap - DEBUG
'"$debug_trap"'
fi' DEBUG;;
esac
}
alias x='oneshot_noglob; any.sh'
Which uses the DEBUG trap to restore set +f after one command has been executed after the set -f.
Now, with all aliases that contain more than one command, that has a few caveats.
echo foo | x
Becomes:
echo foo | oneshort_noglob; any.sh
So the output of echo is only fed to oneshort_noglob.
Same for things like:
cmd && x
Where any.sh would be executed regardless of whether cmd is successful or not.
Also note that it affects all globs in every level of subshell until just before the second command is being executed in the main shell process.
For instance, in x $(echo *; echo *) *, none of those * would be expanded because the DEBUG trap is not inherited unless you set the extdebug option.
One may change something temporarily and then try to return it back to the state it was before. But I propose better, cleaner, more reliable and better maintainable approach: just make needed change local.
Bash allows you to easily achieve that by using a subshell (more info here - Grouping Commands).
In your case it can be done like this
alias x='( set -f;. any.sh ; )'
I didn't get glob to work in bash shell script after trying several settings. Instead, I put a glob in my CLI, and that worked as expected.
Since this didn't work:
sh ./test.sh file
ls "${1}*.ppm"
Replaced it with:
sh ./test.sh file f*.ppm
ls ${2}
Not a direct answer to the question, but a helpful alternative approach for a similar situation.