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).
set -f
to my alias and I put set +f
to my script and It works. Are there some issues to use your approach? If not, I don't know if I should close, delete or answer my self this question.
– John Goofy
Aug 27 '17 at 20:22
set -f
to your script if it's your script that need glob disabled? I'm not sure I understand your use case.
– Stéphane Chazelas
Aug 27 '17 at 20:24
"$foo"
instead of $foo
– Peter Cordes
Aug 28 '17 at 01:10
set -f; find . -name *.cpp; set+f
only do find . -name *.cpp
– builder-7000
Aug 25 '18 at 09:18
*
shell wildcard operator: find . -name '*.cpp'
Or find . -name '[*].cpp'
if you want to find a file called literally *.cpp
.
– Stéphane Chazelas
Aug 25 '18 at 21:38
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.
.
. I have tried your approach with and without source
. However, if my alias looks Iike I have posted and I write to the end of my script set +f
I can pass wildcard arguments and my bash is still able for globbing.
– John Goofy
Aug 27 '17 at 19:53
set +f
to my file and it works.
– John Goofy
Aug 27 '17 at 20:05
.
in my alias, your approach won't work for me as I mentioned.
– John Goofy
Aug 27 '17 at 20:07
any.sh *
with a litteral argument passed to any.sh
as that's the only way I could make sense of your question before you added the .
. It doesn't answer your question now that you've clarified it.
– Stéphane Chazelas
Aug 27 '17 at 20:09
(f)
does not match a word which consists of more than f
. You need *f*
– Hauke Laging
Aug 27 '17 at 20:09
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 ; )'
.
(source
) command as an optimization to avoid spawning another shell subprocess then yes, subshell is not an answer. But it is also worth mentioning that this kind of performance degradation can be noticed in cases like calling scripts in a loop or similar. If user start this from command line by issuing explicit command manually then the performance degradation should be neglectible. Taking into account that this is an alias I assumed that OP plans to call it manually. I may be wrong.
– Victor Yarema
Jul 19 '21 at 11:29
alias x='
cmd₁
;
cmd₂
'
, and then you say x
arg₁ arg₂
, it expands as cmd₁
;
cmd₂ arg₁ arg₂
. With your answer, if the user says x
arg₁ arg₂
, the arguments do not get passed to any.sh
. (3) BTW, you don’t need to have a ;
at the end of a list of commands in parentheses. And it’s traditional to put spaces after semicolons and not before them.
– G-Man Says 'Reinstate Monica'
Aug 29 '22 at 06:30
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.
foobar.sh
but you run it with sh foobar.sh
, then it isn’t 100% a bash shell script any more. (2) Giving scripts names ending with .sh
is discouraged. (3) You may have a situation similar to the one in this question, but I can’t tell what your situation is, and I can’t see what you’re suggesting, or how it would be helpful to anybody. If you believe that you have a unique situation and a solution for it, please post a new question and post an answer there. Be sure to include enough information to make your posts intelligible.
– G-Man Says 'Reinstate Monica'
Aug 28 '22 at 21:17
.sh
or .bash
extension for bash scripts?, Should I save my scripts with the .sh
extension?, .sh
specifying extension?, Commandname Extensions Considered Harmful (Command names should never have filename extensions), … (Cont’d)
– G-Man Says 'Reinstate Monica'
Sep 08 '22 at 09:34
.sh
extension, and somebody makes a comment like mine.
– G-Man Says 'Reinstate Monica'
Sep 08 '22 at 09:34
set -f && any.sh && set +f
...? – George Vasiliou Aug 27 '17 at 19:31any.sh
the commandset +f
and it works. Are there different issues in your or my approach? – John Goofy Aug 27 '17 at 19:36&&
which means that the exit code of previous command must be "success" = "0" for the next command to run. By your approachset +f
can be present anywhere in your script. You can re-enable globbing at will , even if the any.sh script will finally "fail". – George Vasiliou Aug 27 '17 at 19:39set +f
to the end ofany.sh
. – John Goofy Aug 27 '17 at 19:44set -f; any.sh; set +f
orset -f && any.sh && set +f
don't make much sense as there's no glob to be expanded in between thatset -f
and thatset +f
. – Stéphane Chazelas Aug 27 '17 at 19:47subshell
. Just put a part of script in brackets and all options changes which happen inside will be discarded after it. For example:alias x='( set -f;. any.sh ; )'
. – Victor Yarema Jul 16 '21 at 17:52this is what I use to feed e.g.
– axd Sep 27 '21 at 08:05git branch
: