Setting bash options in a compound commandFile globbing pattern, !(*example), behaves differently in bash script than it does in bash shellBash options and interactive shellsBash: Passing command with quoted parameters to functionHow does Bash process a command line?Weird compound-list of dd commands in bashbash command substitution with redirection: bad file descriptorCompare command output inside if statement without subshellHow is a bash script executed via its filename as command name with and without shebang?
SF novella separating the dumb majority from the intelligent part of mankind
How to make a setting relevant?
Is any name of Vishnu Siva?
What is the purpose of building foundations?
Print the string equivalents of a phone number
Traffic law UK, pedestrians
Does the "6 seconds per round" rule apply to speaking/roleplaying during combat situations?
How do I write "Show, Don't Tell" as a person with Asperger Syndrome?
Why is the application of an oracle function not a measurement?
What is this solid state starting relay component?
Cause of continuous spectral lines
How can non-coders use programs on Github?
setting shell options in a compound command
My coworkers think I had a long honeymoon. Actually I was diagnosed with cancer. How do I talk about it?
Why is the relationship between frequency and pitch exponential?
How to translate “Me doing X” like in online posts?
Why don’t airliners have temporary liveries?
Basic question about swap/swap spreads
PL/SQL function to receive a number and return its binary format
What can I, as a user, do about offensive reviews in App Store?
Why only the fundamental frequency component is said to give useful power?
Avoiding cliches when writing gods
2.8 is missing the Carve option in the Boolean Modifier
When writing an error prompt, should we end the sentence with a exclamation mark or a dot?
Setting bash options in a compound command
File globbing pattern, !(*example), behaves differently in bash script than it does in bash shellBash options and interactive shellsBash: Passing command with quoted parameters to functionHow does Bash process a command line?Weird compound-list of dd commands in bashbash command substitution with redirection: bad file descriptorCompare command output inside if statement without subshellHow is a bash script executed via its filename as command name with and without shebang?
.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty margin-bottom:0;
I have found that setting the extglob
shell option within a compound compound results in failure of subsequent anti-globs. Are shell options required to be set outside of compound commands? I did not see an indication of such a requirement in the bash man pages.
As an example, the following script works fine (prints a.0 a.1
):
#!/bin/bash
touch a.0 a.1
a.b.0 a.b.1
shopt -s extglob
ls "a."!(b*)
However, if the last two lines are executed as a compound command, the script fails with the following error:
syntax error near unexpected token `('
` ls "a."!(b*)'
This was tested using bash versions from 4.2 to 4.4 and with a variety of compound commands:
(1) conditional -- if
#!/bin/bash
touch a.0 a.1
a.b.0 a.b.1
if true; then
shopt -s extglob
ls "a."!(b*)
fi
(2) braces --
#!/bin/bash
touch a.0 a.1
a.b.0 a.b.1
shopt -s extglob
ls "a."!(b*)
(3) subshell -- ( )
:
#!/bin/bash
touch a.0 a.1
a.b.0 a.b.1
(
shopt -s extglob
ls "a."!(b*)
)
In all cases, if the shopt
is moved outside the compound command, the script succeeds.
bash shopt
add a comment |
I have found that setting the extglob
shell option within a compound compound results in failure of subsequent anti-globs. Are shell options required to be set outside of compound commands? I did not see an indication of such a requirement in the bash man pages.
As an example, the following script works fine (prints a.0 a.1
):
#!/bin/bash
touch a.0 a.1
a.b.0 a.b.1
shopt -s extglob
ls "a."!(b*)
However, if the last two lines are executed as a compound command, the script fails with the following error:
syntax error near unexpected token `('
` ls "a."!(b*)'
This was tested using bash versions from 4.2 to 4.4 and with a variety of compound commands:
(1) conditional -- if
#!/bin/bash
touch a.0 a.1
a.b.0 a.b.1
if true; then
shopt -s extglob
ls "a."!(b*)
fi
(2) braces --
#!/bin/bash
touch a.0 a.1
a.b.0 a.b.1
shopt -s extglob
ls "a."!(b*)
(3) subshell -- ( )
:
#!/bin/bash
touch a.0 a.1
a.b.0 a.b.1
(
shopt -s extglob
ls "a."!(b*)
)
In all cases, if the shopt
is moved outside the compound command, the script succeeds.
bash shopt
add a comment |
I have found that setting the extglob
shell option within a compound compound results in failure of subsequent anti-globs. Are shell options required to be set outside of compound commands? I did not see an indication of such a requirement in the bash man pages.
As an example, the following script works fine (prints a.0 a.1
):
#!/bin/bash
touch a.0 a.1
a.b.0 a.b.1
shopt -s extglob
ls "a."!(b*)
However, if the last two lines are executed as a compound command, the script fails with the following error:
syntax error near unexpected token `('
` ls "a."!(b*)'
This was tested using bash versions from 4.2 to 4.4 and with a variety of compound commands:
(1) conditional -- if
#!/bin/bash
touch a.0 a.1
a.b.0 a.b.1
if true; then
shopt -s extglob
ls "a."!(b*)
fi
(2) braces --
#!/bin/bash
touch a.0 a.1
a.b.0 a.b.1
shopt -s extglob
ls "a."!(b*)
(3) subshell -- ( )
:
#!/bin/bash
touch a.0 a.1
a.b.0 a.b.1
(
shopt -s extglob
ls "a."!(b*)
)
In all cases, if the shopt
is moved outside the compound command, the script succeeds.
bash shopt
I have found that setting the extglob
shell option within a compound compound results in failure of subsequent anti-globs. Are shell options required to be set outside of compound commands? I did not see an indication of such a requirement in the bash man pages.
As an example, the following script works fine (prints a.0 a.1
):
#!/bin/bash
touch a.0 a.1
a.b.0 a.b.1
shopt -s extglob
ls "a."!(b*)
However, if the last two lines are executed as a compound command, the script fails with the following error:
syntax error near unexpected token `('
` ls "a."!(b*)'
This was tested using bash versions from 4.2 to 4.4 and with a variety of compound commands:
(1) conditional -- if
#!/bin/bash
touch a.0 a.1
a.b.0 a.b.1
if true; then
shopt -s extglob
ls "a."!(b*)
fi
(2) braces --
#!/bin/bash
touch a.0 a.1
a.b.0 a.b.1
shopt -s extglob
ls "a."!(b*)
(3) subshell -- ( )
:
#!/bin/bash
touch a.0 a.1
a.b.0 a.b.1
(
shopt -s extglob
ls "a."!(b*)
)
In all cases, if the shopt
is moved outside the compound command, the script succeeds.
bash shopt
bash shopt
edited 7 mins ago
Gilles
556k13411421651
556k13411421651
asked 8 hours ago
user001user001
1,67332141
1,67332141
add a comment |
add a comment |
1 Answer
1
active
oldest
votes
No part of a compound command executes before the entire command is parsed, which is obliquely documented in the Shell Operation section of the manual: all tokenising and parsing happens before "the" command executes. Enabling extglob
changes the language syntax by adding new pattern-matching operators, which are recognised during tokenisation.
Because the shopt
command hasn't executed at the time !(
is reached, it's seen as either an attempted history expansion (!
) or the control operator (
, rather than !(
being seen as a single item (and the same for @(
, etc, except that there's no history expansion there).
When parsing reaches that token either case will generally be an error, though !(...)
at the start of a line or after time
is a negated subshell pipeline. "unexpected token `('
" means it couldn't accept a subshell expression in that spot.
This is somewhat annoying when you want extglob enabled only temporarily in a subshell. One workaround is to define a function that uses the glob you want, then re-disable extglob, and then call the function from the subshell with extglob enabled:
shopt -s extglob
f() ls "a."!(b*) ;
shopt -u extglob
(
shopt -s extglob
f
)
It's very clunky.
The same effect happens if you create an alias within a compound command, because they are also processed before parsing:
if true
then
alias foo=echo
foo bar
fi
foo xyz
will print foo: command not found
, and then xyz
, because the alias is created, but not available until the if
is done.
Thanks -- I didn't realize that compound commands were parsed as a unit before execution. The behavior now makes sense.
– user001
7 hours ago
2
@user001 I wouldn't be so charitable to say that it makes sense. Switching the lexer's mode while in parsing is nothing unheard of, and other languages likeC
orperl
are able to do it fine. Notice that not being part of a compound command isn't enough,shopt -s extglob
also has to be on a separate line. See also the discussion and examples here
– mosvy
6 hours ago
@mosvy: I meant that the observed behavior makes sense once one realizes that bash parses a compound command as a unit (not that the limitations of the parser are necessarily reasonable). Thanks for linking to the discussion in the other post.
– user001
2 hours ago
add a comment |
Your Answer
StackExchange.ready(function()
var channelOptions =
tags: "".split(" "),
id: "106"
;
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function()
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled)
StackExchange.using("snippets", function()
createEditor();
);
else
createEditor();
);
function createEditor()
StackExchange.prepareEditor(
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: false,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: null,
bindNavPrevention: true,
postfix: "",
imageUploader:
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
,
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
);
);
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2funix.stackexchange.com%2fquestions%2f522511%2fsetting-bash-options-in-a-compound-command%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
No part of a compound command executes before the entire command is parsed, which is obliquely documented in the Shell Operation section of the manual: all tokenising and parsing happens before "the" command executes. Enabling extglob
changes the language syntax by adding new pattern-matching operators, which are recognised during tokenisation.
Because the shopt
command hasn't executed at the time !(
is reached, it's seen as either an attempted history expansion (!
) or the control operator (
, rather than !(
being seen as a single item (and the same for @(
, etc, except that there's no history expansion there).
When parsing reaches that token either case will generally be an error, though !(...)
at the start of a line or after time
is a negated subshell pipeline. "unexpected token `('
" means it couldn't accept a subshell expression in that spot.
This is somewhat annoying when you want extglob enabled only temporarily in a subshell. One workaround is to define a function that uses the glob you want, then re-disable extglob, and then call the function from the subshell with extglob enabled:
shopt -s extglob
f() ls "a."!(b*) ;
shopt -u extglob
(
shopt -s extglob
f
)
It's very clunky.
The same effect happens if you create an alias within a compound command, because they are also processed before parsing:
if true
then
alias foo=echo
foo bar
fi
foo xyz
will print foo: command not found
, and then xyz
, because the alias is created, but not available until the if
is done.
Thanks -- I didn't realize that compound commands were parsed as a unit before execution. The behavior now makes sense.
– user001
7 hours ago
2
@user001 I wouldn't be so charitable to say that it makes sense. Switching the lexer's mode while in parsing is nothing unheard of, and other languages likeC
orperl
are able to do it fine. Notice that not being part of a compound command isn't enough,shopt -s extglob
also has to be on a separate line. See also the discussion and examples here
– mosvy
6 hours ago
@mosvy: I meant that the observed behavior makes sense once one realizes that bash parses a compound command as a unit (not that the limitations of the parser are necessarily reasonable). Thanks for linking to the discussion in the other post.
– user001
2 hours ago
add a comment |
No part of a compound command executes before the entire command is parsed, which is obliquely documented in the Shell Operation section of the manual: all tokenising and parsing happens before "the" command executes. Enabling extglob
changes the language syntax by adding new pattern-matching operators, which are recognised during tokenisation.
Because the shopt
command hasn't executed at the time !(
is reached, it's seen as either an attempted history expansion (!
) or the control operator (
, rather than !(
being seen as a single item (and the same for @(
, etc, except that there's no history expansion there).
When parsing reaches that token either case will generally be an error, though !(...)
at the start of a line or after time
is a negated subshell pipeline. "unexpected token `('
" means it couldn't accept a subshell expression in that spot.
This is somewhat annoying when you want extglob enabled only temporarily in a subshell. One workaround is to define a function that uses the glob you want, then re-disable extglob, and then call the function from the subshell with extglob enabled:
shopt -s extglob
f() ls "a."!(b*) ;
shopt -u extglob
(
shopt -s extglob
f
)
It's very clunky.
The same effect happens if you create an alias within a compound command, because they are also processed before parsing:
if true
then
alias foo=echo
foo bar
fi
foo xyz
will print foo: command not found
, and then xyz
, because the alias is created, but not available until the if
is done.
Thanks -- I didn't realize that compound commands were parsed as a unit before execution. The behavior now makes sense.
– user001
7 hours ago
2
@user001 I wouldn't be so charitable to say that it makes sense. Switching the lexer's mode while in parsing is nothing unheard of, and other languages likeC
orperl
are able to do it fine. Notice that not being part of a compound command isn't enough,shopt -s extglob
also has to be on a separate line. See also the discussion and examples here
– mosvy
6 hours ago
@mosvy: I meant that the observed behavior makes sense once one realizes that bash parses a compound command as a unit (not that the limitations of the parser are necessarily reasonable). Thanks for linking to the discussion in the other post.
– user001
2 hours ago
add a comment |
No part of a compound command executes before the entire command is parsed, which is obliquely documented in the Shell Operation section of the manual: all tokenising and parsing happens before "the" command executes. Enabling extglob
changes the language syntax by adding new pattern-matching operators, which are recognised during tokenisation.
Because the shopt
command hasn't executed at the time !(
is reached, it's seen as either an attempted history expansion (!
) or the control operator (
, rather than !(
being seen as a single item (and the same for @(
, etc, except that there's no history expansion there).
When parsing reaches that token either case will generally be an error, though !(...)
at the start of a line or after time
is a negated subshell pipeline. "unexpected token `('
" means it couldn't accept a subshell expression in that spot.
This is somewhat annoying when you want extglob enabled only temporarily in a subshell. One workaround is to define a function that uses the glob you want, then re-disable extglob, and then call the function from the subshell with extglob enabled:
shopt -s extglob
f() ls "a."!(b*) ;
shopt -u extglob
(
shopt -s extglob
f
)
It's very clunky.
The same effect happens if you create an alias within a compound command, because they are also processed before parsing:
if true
then
alias foo=echo
foo bar
fi
foo xyz
will print foo: command not found
, and then xyz
, because the alias is created, but not available until the if
is done.
No part of a compound command executes before the entire command is parsed, which is obliquely documented in the Shell Operation section of the manual: all tokenising and parsing happens before "the" command executes. Enabling extglob
changes the language syntax by adding new pattern-matching operators, which are recognised during tokenisation.
Because the shopt
command hasn't executed at the time !(
is reached, it's seen as either an attempted history expansion (!
) or the control operator (
, rather than !(
being seen as a single item (and the same for @(
, etc, except that there's no history expansion there).
When parsing reaches that token either case will generally be an error, though !(...)
at the start of a line or after time
is a negated subshell pipeline. "unexpected token `('
" means it couldn't accept a subshell expression in that spot.
This is somewhat annoying when you want extglob enabled only temporarily in a subshell. One workaround is to define a function that uses the glob you want, then re-disable extglob, and then call the function from the subshell with extglob enabled:
shopt -s extglob
f() ls "a."!(b*) ;
shopt -u extglob
(
shopt -s extglob
f
)
It's very clunky.
The same effect happens if you create an alias within a compound command, because they are also processed before parsing:
if true
then
alias foo=echo
foo bar
fi
foo xyz
will print foo: command not found
, and then xyz
, because the alias is created, but not available until the if
is done.
answered 8 hours ago
Michael HomerMichael Homer
52.9k9146183
52.9k9146183
Thanks -- I didn't realize that compound commands were parsed as a unit before execution. The behavior now makes sense.
– user001
7 hours ago
2
@user001 I wouldn't be so charitable to say that it makes sense. Switching the lexer's mode while in parsing is nothing unheard of, and other languages likeC
orperl
are able to do it fine. Notice that not being part of a compound command isn't enough,shopt -s extglob
also has to be on a separate line. See also the discussion and examples here
– mosvy
6 hours ago
@mosvy: I meant that the observed behavior makes sense once one realizes that bash parses a compound command as a unit (not that the limitations of the parser are necessarily reasonable). Thanks for linking to the discussion in the other post.
– user001
2 hours ago
add a comment |
Thanks -- I didn't realize that compound commands were parsed as a unit before execution. The behavior now makes sense.
– user001
7 hours ago
2
@user001 I wouldn't be so charitable to say that it makes sense. Switching the lexer's mode while in parsing is nothing unheard of, and other languages likeC
orperl
are able to do it fine. Notice that not being part of a compound command isn't enough,shopt -s extglob
also has to be on a separate line. See also the discussion and examples here
– mosvy
6 hours ago
@mosvy: I meant that the observed behavior makes sense once one realizes that bash parses a compound command as a unit (not that the limitations of the parser are necessarily reasonable). Thanks for linking to the discussion in the other post.
– user001
2 hours ago
Thanks -- I didn't realize that compound commands were parsed as a unit before execution. The behavior now makes sense.
– user001
7 hours ago
Thanks -- I didn't realize that compound commands were parsed as a unit before execution. The behavior now makes sense.
– user001
7 hours ago
2
2
@user001 I wouldn't be so charitable to say that it makes sense. Switching the lexer's mode while in parsing is nothing unheard of, and other languages like
C
or perl
are able to do it fine. Notice that not being part of a compound command isn't enough, shopt -s extglob
also has to be on a separate line. See also the discussion and examples here– mosvy
6 hours ago
@user001 I wouldn't be so charitable to say that it makes sense. Switching the lexer's mode while in parsing is nothing unheard of, and other languages like
C
or perl
are able to do it fine. Notice that not being part of a compound command isn't enough, shopt -s extglob
also has to be on a separate line. See also the discussion and examples here– mosvy
6 hours ago
@mosvy: I meant that the observed behavior makes sense once one realizes that bash parses a compound command as a unit (not that the limitations of the parser are necessarily reasonable). Thanks for linking to the discussion in the other post.
– user001
2 hours ago
@mosvy: I meant that the observed behavior makes sense once one realizes that bash parses a compound command as a unit (not that the limitations of the parser are necessarily reasonable). Thanks for linking to the discussion in the other post.
– user001
2 hours ago
add a comment |
Thanks for contributing an answer to Unix & Linux Stack Exchange!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2funix.stackexchange.com%2fquestions%2f522511%2fsetting-bash-options-in-a-compound-command%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown