File with parentheses/brackets in working directory causes eval error
I encountered a strange bug today, when running a script in a directory containing a directory with parentheses in it, such as a()
.
Minimal working example
I managed to reduce the bug to the following minimal working example:
Create an empty directory in /tmp
and cd
into it:
mkdir /tmp/foo
cd /tmp/foo
Create a script named foo.sh in it containing:
foo() {
somevar=1;
case somevar in
aha) echo "something" ;;
*) echo "other" ;;
esac;
};
Run the following command:
eval $(/bin/cat foo.sh)
There should not be any error.
Create a file with parentheses:
touch "a()"
Run the command again:
eval $(/bin/cat foo.sh)
I now get the error:
bash: syntax error near unexpected token `('
Why does bash even care about what files are in the directory? Why do parentheses cause an error?
System information:
$ bash --version
GNU bash, version 4.4.19(1)-release (x86_64-pc-linux-gnu)
Copyright © 2016 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software; you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
$ lsb_release -a
No LSB modules are available.
Distributor ID: Ubuntu
Description: Ubuntu 18.04.1 LTS
Release: 18.04
Codename: bionic
More detailed background and original error:
My problem came from using a script sourcing /usr/share/modules/init/bash
from the environment-modules
package, as summarized here:
$ dpkg -l environment-modules
Desired=Unknown/Install/Remove/Purge/Hold
| Status=Not/Inst/Conf-files/Unpacked/halF-conf/Half-inst/trig-aWait/Trig-pend
|/ Err?=(none)/Reinst-required (Status,Err: uppercase=bad)
||/ Name Version Architecture Description
+++-=============================================================-===================================-===================================-================================================================================================================================
ii environment-modules 4.1.1-1 amd64 Modular system for handling environment variables
$ source /usr/share/modules/init/bash
$ touch "a()"
$ source /usr/share/modules/init/bash
bash: eval: line 43: syntax error near unexpected token `('
bash: eval: line 43: ` a() _mlshdbg='' ;;'
bash eval module
add a comment |
I encountered a strange bug today, when running a script in a directory containing a directory with parentheses in it, such as a()
.
Minimal working example
I managed to reduce the bug to the following minimal working example:
Create an empty directory in /tmp
and cd
into it:
mkdir /tmp/foo
cd /tmp/foo
Create a script named foo.sh in it containing:
foo() {
somevar=1;
case somevar in
aha) echo "something" ;;
*) echo "other" ;;
esac;
};
Run the following command:
eval $(/bin/cat foo.sh)
There should not be any error.
Create a file with parentheses:
touch "a()"
Run the command again:
eval $(/bin/cat foo.sh)
I now get the error:
bash: syntax error near unexpected token `('
Why does bash even care about what files are in the directory? Why do parentheses cause an error?
System information:
$ bash --version
GNU bash, version 4.4.19(1)-release (x86_64-pc-linux-gnu)
Copyright © 2016 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software; you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
$ lsb_release -a
No LSB modules are available.
Distributor ID: Ubuntu
Description: Ubuntu 18.04.1 LTS
Release: 18.04
Codename: bionic
More detailed background and original error:
My problem came from using a script sourcing /usr/share/modules/init/bash
from the environment-modules
package, as summarized here:
$ dpkg -l environment-modules
Desired=Unknown/Install/Remove/Purge/Hold
| Status=Not/Inst/Conf-files/Unpacked/halF-conf/Half-inst/trig-aWait/Trig-pend
|/ Err?=(none)/Reinst-required (Status,Err: uppercase=bad)
||/ Name Version Architecture Description
+++-=============================================================-===================================-===================================-================================================================================================================================
ii environment-modules 4.1.1-1 amd64 Modular system for handling environment variables
$ source /usr/share/modules/init/bash
$ touch "a()"
$ source /usr/share/modules/init/bash
bash: eval: line 43: syntax error near unexpected token `('
bash: eval: line 43: ` a() _mlshdbg='' ;;'
bash eval module
It appears this has already been reported as a bug (and fixed) to the environment-modules package here: github.com/cea-hpc/modules/issues/220 and adding single/double quotes fixes the error. My test script could be simplified to "echo *". But why? Bash and its expansion system still confuses me... I was considering updating my question or answering, but I would really appreciate a clear explanation to what exactly is happening.
– KIAaze
Feb 17 at 17:21
I'm tempted to mark this as a duplicate of Why does my shell script choke on whitespace or other special characters?
– ilkkachu
Feb 17 at 18:01
add a comment |
I encountered a strange bug today, when running a script in a directory containing a directory with parentheses in it, such as a()
.
Minimal working example
I managed to reduce the bug to the following minimal working example:
Create an empty directory in /tmp
and cd
into it:
mkdir /tmp/foo
cd /tmp/foo
Create a script named foo.sh in it containing:
foo() {
somevar=1;
case somevar in
aha) echo "something" ;;
*) echo "other" ;;
esac;
};
Run the following command:
eval $(/bin/cat foo.sh)
There should not be any error.
Create a file with parentheses:
touch "a()"
Run the command again:
eval $(/bin/cat foo.sh)
I now get the error:
bash: syntax error near unexpected token `('
Why does bash even care about what files are in the directory? Why do parentheses cause an error?
System information:
$ bash --version
GNU bash, version 4.4.19(1)-release (x86_64-pc-linux-gnu)
Copyright © 2016 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software; you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
$ lsb_release -a
No LSB modules are available.
Distributor ID: Ubuntu
Description: Ubuntu 18.04.1 LTS
Release: 18.04
Codename: bionic
More detailed background and original error:
My problem came from using a script sourcing /usr/share/modules/init/bash
from the environment-modules
package, as summarized here:
$ dpkg -l environment-modules
Desired=Unknown/Install/Remove/Purge/Hold
| Status=Not/Inst/Conf-files/Unpacked/halF-conf/Half-inst/trig-aWait/Trig-pend
|/ Err?=(none)/Reinst-required (Status,Err: uppercase=bad)
||/ Name Version Architecture Description
+++-=============================================================-===================================-===================================-================================================================================================================================
ii environment-modules 4.1.1-1 amd64 Modular system for handling environment variables
$ source /usr/share/modules/init/bash
$ touch "a()"
$ source /usr/share/modules/init/bash
bash: eval: line 43: syntax error near unexpected token `('
bash: eval: line 43: ` a() _mlshdbg='' ;;'
bash eval module
I encountered a strange bug today, when running a script in a directory containing a directory with parentheses in it, such as a()
.
Minimal working example
I managed to reduce the bug to the following minimal working example:
Create an empty directory in /tmp
and cd
into it:
mkdir /tmp/foo
cd /tmp/foo
Create a script named foo.sh in it containing:
foo() {
somevar=1;
case somevar in
aha) echo "something" ;;
*) echo "other" ;;
esac;
};
Run the following command:
eval $(/bin/cat foo.sh)
There should not be any error.
Create a file with parentheses:
touch "a()"
Run the command again:
eval $(/bin/cat foo.sh)
I now get the error:
bash: syntax error near unexpected token `('
Why does bash even care about what files are in the directory? Why do parentheses cause an error?
System information:
$ bash --version
GNU bash, version 4.4.19(1)-release (x86_64-pc-linux-gnu)
Copyright © 2016 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software; you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
$ lsb_release -a
No LSB modules are available.
Distributor ID: Ubuntu
Description: Ubuntu 18.04.1 LTS
Release: 18.04
Codename: bionic
More detailed background and original error:
My problem came from using a script sourcing /usr/share/modules/init/bash
from the environment-modules
package, as summarized here:
$ dpkg -l environment-modules
Desired=Unknown/Install/Remove/Purge/Hold
| Status=Not/Inst/Conf-files/Unpacked/halF-conf/Half-inst/trig-aWait/Trig-pend
|/ Err?=(none)/Reinst-required (Status,Err: uppercase=bad)
||/ Name Version Architecture Description
+++-=============================================================-===================================-===================================-================================================================================================================================
ii environment-modules 4.1.1-1 amd64 Modular system for handling environment variables
$ source /usr/share/modules/init/bash
$ touch "a()"
$ source /usr/share/modules/init/bash
bash: eval: line 43: syntax error near unexpected token `('
bash: eval: line 43: ` a() _mlshdbg='' ;;'
bash eval module
bash eval module
edited Feb 18 at 13:16
Kusalananda
132k17252414
132k17252414
asked Feb 17 at 16:07
KIAazeKIAaze
310213
310213
It appears this has already been reported as a bug (and fixed) to the environment-modules package here: github.com/cea-hpc/modules/issues/220 and adding single/double quotes fixes the error. My test script could be simplified to "echo *". But why? Bash and its expansion system still confuses me... I was considering updating my question or answering, but I would really appreciate a clear explanation to what exactly is happening.
– KIAaze
Feb 17 at 17:21
I'm tempted to mark this as a duplicate of Why does my shell script choke on whitespace or other special characters?
– ilkkachu
Feb 17 at 18:01
add a comment |
It appears this has already been reported as a bug (and fixed) to the environment-modules package here: github.com/cea-hpc/modules/issues/220 and adding single/double quotes fixes the error. My test script could be simplified to "echo *". But why? Bash and its expansion system still confuses me... I was considering updating my question or answering, but I would really appreciate a clear explanation to what exactly is happening.
– KIAaze
Feb 17 at 17:21
I'm tempted to mark this as a duplicate of Why does my shell script choke on whitespace or other special characters?
– ilkkachu
Feb 17 at 18:01
It appears this has already been reported as a bug (and fixed) to the environment-modules package here: github.com/cea-hpc/modules/issues/220 and adding single/double quotes fixes the error. My test script could be simplified to "echo *". But why? Bash and its expansion system still confuses me... I was considering updating my question or answering, but I would really appreciate a clear explanation to what exactly is happening.
– KIAaze
Feb 17 at 17:21
It appears this has already been reported as a bug (and fixed) to the environment-modules package here: github.com/cea-hpc/modules/issues/220 and adding single/double quotes fixes the error. My test script could be simplified to "echo *". But why? Bash and its expansion system still confuses me... I was considering updating my question or answering, but I would really appreciate a clear explanation to what exactly is happening.
– KIAaze
Feb 17 at 17:21
I'm tempted to mark this as a duplicate of Why does my shell script choke on whitespace or other special characters?
– ilkkachu
Feb 17 at 18:01
I'm tempted to mark this as a duplicate of Why does my shell script choke on whitespace or other special characters?
– ilkkachu
Feb 17 at 18:01
add a comment |
1 Answer
1
active
oldest
votes
This is neither strange nor a bug in bash
(it does seem to be a bug in /usr/share/modules/init/bash
though). You are using an unquoted command substitution together with eval
. The string that is the result of the command substitution will, since it is unquoted, undergo word splitting and filename expansion (globbing). The *)
in the code matches the filename a()
, so it is replace by this filename in the filename expansion stage.
Running your example under set -x
highlights this:
$ eval $(cat foo.sh)
++ cat foo.sh
+ eval 'foo()' '{' 'somevar=1;' case somevar in 'aha)' echo '"something"' ';;' 'a()' echo '"other"' ';;' 'esac;' '};'
bash: syntax error near unexpected token `('
The same thing in the yash
shell:
$ eval $(cat foo.sh)
+ cat foo.sh
+ eval 'foo()' '{' 'somevar=1;' case somevar in 'aha)' echo '"something"' ';;' 'a()' echo '"other"' ';;' 'esac;' '};'
eval:1: syntax error: `)' is missing
eval:1: syntax error: `esac' is missing
eval:1: syntax error: `}' is missing
And with ksh93
:
$ eval $(cat foo.sh)
+ cat foo.sh
+ eval 'foo()' '{' somevar='1;' case somevar in 'aha)' echo '"something"' ';;' 'a()' echo '"other"' ';;' 'esac;' '};'
ksh93: eval: syntax error: `(' unexpected
And dash
:
$ eval $(cat foo.sh)
+ cat foo.sh
+ eval foo() { somevar=1; case somevar in aha) echo "something" ;; a() echo "other" ;; esac; };
dash: 1: eval: Syntax error: "(" unexpected (expecting ")")
Only the zsh
would handle this as it does not perform the globbing:
$ eval $(cat foo.sh)
+zsh:2> cat foo.sh
+zsh:2> eval 'foo()' '{' 'somevar=1;' case somevar in 'aha)' echo '"something"' ';;' '*)' echo '"other"' ';;' 'esac;' '};'
The correct way to handle this would be to source the foo.sh
script:
. ./foo.sh
There is really no reason to use eval "$(cat foo.sh)"
as far as I can see.
This is also a code injection vulnerability:
$ touch '*) echo "hello" ;; *)'
$ eval $(cat foo.sh)
$ declare -f foo
foo ()
{
somevar=1;
case somevar in
aha)
echo "something"
;;
*)
echo "hello"
;;
*)
echo "other"
;;
esac
}
Another way of breaking this command easily without creating a specially named file, is to set the IFS
variable to a set of characters other than the default:
$ IFS=';{} '
+ IFS=';{} '
$ eval $(cat foo.sh)
++ cat foo.sh
+ eval 'foo()' '
' somevar=1 '
' case somevar 'in
' 'aha)' echo '"something"' '' '
' '*)' echo '"other"' '' '
' esac '
' ''
bash: syntax error near unexpected token `somevar=1'
This breaks it because of the word-splitting step rather than the file globbing step in the evaluation of the arguments to eval
. With IFS=';{} '
, each of those characters would be used to split the text in foo.sh
up into words (and those characters would then be removed from the string).
Not even zsh
would be immune to this:
$ IFS=';{} '
+zsh:2> IFS=';{} '
$ eval $(cat foo.sh)
+zsh:3> cat foo.sh
+zsh:3> eval 'foo()' $'n' 'somevar=1' $'n' case somevar $'inn' 'aha)' echo '"something"' '' $'n' '*)' echo '"other"' '' $'n' esac $'n' '' ''
zsh: parse error near `)'
Related:
- Security implications of forgetting to quote a variable in bash/POSIX shells
- When is double-quoting necessary?
- Why does my shell script choke on whitespace or other special characters?
1
Thanks. I learned a bit more about bash again. :) (In particular, "set -f" can fix the error too by disable filename expansion.) I also finally upgraded to Ubuntu 18.10, which fixed the environment-modules error.
– KIAaze
Feb 18 at 22:06
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%2f501188%2ffile-with-parentheses-brackets-in-working-directory-causes-eval-error%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
This is neither strange nor a bug in bash
(it does seem to be a bug in /usr/share/modules/init/bash
though). You are using an unquoted command substitution together with eval
. The string that is the result of the command substitution will, since it is unquoted, undergo word splitting and filename expansion (globbing). The *)
in the code matches the filename a()
, so it is replace by this filename in the filename expansion stage.
Running your example under set -x
highlights this:
$ eval $(cat foo.sh)
++ cat foo.sh
+ eval 'foo()' '{' 'somevar=1;' case somevar in 'aha)' echo '"something"' ';;' 'a()' echo '"other"' ';;' 'esac;' '};'
bash: syntax error near unexpected token `('
The same thing in the yash
shell:
$ eval $(cat foo.sh)
+ cat foo.sh
+ eval 'foo()' '{' 'somevar=1;' case somevar in 'aha)' echo '"something"' ';;' 'a()' echo '"other"' ';;' 'esac;' '};'
eval:1: syntax error: `)' is missing
eval:1: syntax error: `esac' is missing
eval:1: syntax error: `}' is missing
And with ksh93
:
$ eval $(cat foo.sh)
+ cat foo.sh
+ eval 'foo()' '{' somevar='1;' case somevar in 'aha)' echo '"something"' ';;' 'a()' echo '"other"' ';;' 'esac;' '};'
ksh93: eval: syntax error: `(' unexpected
And dash
:
$ eval $(cat foo.sh)
+ cat foo.sh
+ eval foo() { somevar=1; case somevar in aha) echo "something" ;; a() echo "other" ;; esac; };
dash: 1: eval: Syntax error: "(" unexpected (expecting ")")
Only the zsh
would handle this as it does not perform the globbing:
$ eval $(cat foo.sh)
+zsh:2> cat foo.sh
+zsh:2> eval 'foo()' '{' 'somevar=1;' case somevar in 'aha)' echo '"something"' ';;' '*)' echo '"other"' ';;' 'esac;' '};'
The correct way to handle this would be to source the foo.sh
script:
. ./foo.sh
There is really no reason to use eval "$(cat foo.sh)"
as far as I can see.
This is also a code injection vulnerability:
$ touch '*) echo "hello" ;; *)'
$ eval $(cat foo.sh)
$ declare -f foo
foo ()
{
somevar=1;
case somevar in
aha)
echo "something"
;;
*)
echo "hello"
;;
*)
echo "other"
;;
esac
}
Another way of breaking this command easily without creating a specially named file, is to set the IFS
variable to a set of characters other than the default:
$ IFS=';{} '
+ IFS=';{} '
$ eval $(cat foo.sh)
++ cat foo.sh
+ eval 'foo()' '
' somevar=1 '
' case somevar 'in
' 'aha)' echo '"something"' '' '
' '*)' echo '"other"' '' '
' esac '
' ''
bash: syntax error near unexpected token `somevar=1'
This breaks it because of the word-splitting step rather than the file globbing step in the evaluation of the arguments to eval
. With IFS=';{} '
, each of those characters would be used to split the text in foo.sh
up into words (and those characters would then be removed from the string).
Not even zsh
would be immune to this:
$ IFS=';{} '
+zsh:2> IFS=';{} '
$ eval $(cat foo.sh)
+zsh:3> cat foo.sh
+zsh:3> eval 'foo()' $'n' 'somevar=1' $'n' case somevar $'inn' 'aha)' echo '"something"' '' $'n' '*)' echo '"other"' '' $'n' esac $'n' '' ''
zsh: parse error near `)'
Related:
- Security implications of forgetting to quote a variable in bash/POSIX shells
- When is double-quoting necessary?
- Why does my shell script choke on whitespace or other special characters?
1
Thanks. I learned a bit more about bash again. :) (In particular, "set -f" can fix the error too by disable filename expansion.) I also finally upgraded to Ubuntu 18.10, which fixed the environment-modules error.
– KIAaze
Feb 18 at 22:06
add a comment |
This is neither strange nor a bug in bash
(it does seem to be a bug in /usr/share/modules/init/bash
though). You are using an unquoted command substitution together with eval
. The string that is the result of the command substitution will, since it is unquoted, undergo word splitting and filename expansion (globbing). The *)
in the code matches the filename a()
, so it is replace by this filename in the filename expansion stage.
Running your example under set -x
highlights this:
$ eval $(cat foo.sh)
++ cat foo.sh
+ eval 'foo()' '{' 'somevar=1;' case somevar in 'aha)' echo '"something"' ';;' 'a()' echo '"other"' ';;' 'esac;' '};'
bash: syntax error near unexpected token `('
The same thing in the yash
shell:
$ eval $(cat foo.sh)
+ cat foo.sh
+ eval 'foo()' '{' 'somevar=1;' case somevar in 'aha)' echo '"something"' ';;' 'a()' echo '"other"' ';;' 'esac;' '};'
eval:1: syntax error: `)' is missing
eval:1: syntax error: `esac' is missing
eval:1: syntax error: `}' is missing
And with ksh93
:
$ eval $(cat foo.sh)
+ cat foo.sh
+ eval 'foo()' '{' somevar='1;' case somevar in 'aha)' echo '"something"' ';;' 'a()' echo '"other"' ';;' 'esac;' '};'
ksh93: eval: syntax error: `(' unexpected
And dash
:
$ eval $(cat foo.sh)
+ cat foo.sh
+ eval foo() { somevar=1; case somevar in aha) echo "something" ;; a() echo "other" ;; esac; };
dash: 1: eval: Syntax error: "(" unexpected (expecting ")")
Only the zsh
would handle this as it does not perform the globbing:
$ eval $(cat foo.sh)
+zsh:2> cat foo.sh
+zsh:2> eval 'foo()' '{' 'somevar=1;' case somevar in 'aha)' echo '"something"' ';;' '*)' echo '"other"' ';;' 'esac;' '};'
The correct way to handle this would be to source the foo.sh
script:
. ./foo.sh
There is really no reason to use eval "$(cat foo.sh)"
as far as I can see.
This is also a code injection vulnerability:
$ touch '*) echo "hello" ;; *)'
$ eval $(cat foo.sh)
$ declare -f foo
foo ()
{
somevar=1;
case somevar in
aha)
echo "something"
;;
*)
echo "hello"
;;
*)
echo "other"
;;
esac
}
Another way of breaking this command easily without creating a specially named file, is to set the IFS
variable to a set of characters other than the default:
$ IFS=';{} '
+ IFS=';{} '
$ eval $(cat foo.sh)
++ cat foo.sh
+ eval 'foo()' '
' somevar=1 '
' case somevar 'in
' 'aha)' echo '"something"' '' '
' '*)' echo '"other"' '' '
' esac '
' ''
bash: syntax error near unexpected token `somevar=1'
This breaks it because of the word-splitting step rather than the file globbing step in the evaluation of the arguments to eval
. With IFS=';{} '
, each of those characters would be used to split the text in foo.sh
up into words (and those characters would then be removed from the string).
Not even zsh
would be immune to this:
$ IFS=';{} '
+zsh:2> IFS=';{} '
$ eval $(cat foo.sh)
+zsh:3> cat foo.sh
+zsh:3> eval 'foo()' $'n' 'somevar=1' $'n' case somevar $'inn' 'aha)' echo '"something"' '' $'n' '*)' echo '"other"' '' $'n' esac $'n' '' ''
zsh: parse error near `)'
Related:
- Security implications of forgetting to quote a variable in bash/POSIX shells
- When is double-quoting necessary?
- Why does my shell script choke on whitespace or other special characters?
1
Thanks. I learned a bit more about bash again. :) (In particular, "set -f" can fix the error too by disable filename expansion.) I also finally upgraded to Ubuntu 18.10, which fixed the environment-modules error.
– KIAaze
Feb 18 at 22:06
add a comment |
This is neither strange nor a bug in bash
(it does seem to be a bug in /usr/share/modules/init/bash
though). You are using an unquoted command substitution together with eval
. The string that is the result of the command substitution will, since it is unquoted, undergo word splitting and filename expansion (globbing). The *)
in the code matches the filename a()
, so it is replace by this filename in the filename expansion stage.
Running your example under set -x
highlights this:
$ eval $(cat foo.sh)
++ cat foo.sh
+ eval 'foo()' '{' 'somevar=1;' case somevar in 'aha)' echo '"something"' ';;' 'a()' echo '"other"' ';;' 'esac;' '};'
bash: syntax error near unexpected token `('
The same thing in the yash
shell:
$ eval $(cat foo.sh)
+ cat foo.sh
+ eval 'foo()' '{' 'somevar=1;' case somevar in 'aha)' echo '"something"' ';;' 'a()' echo '"other"' ';;' 'esac;' '};'
eval:1: syntax error: `)' is missing
eval:1: syntax error: `esac' is missing
eval:1: syntax error: `}' is missing
And with ksh93
:
$ eval $(cat foo.sh)
+ cat foo.sh
+ eval 'foo()' '{' somevar='1;' case somevar in 'aha)' echo '"something"' ';;' 'a()' echo '"other"' ';;' 'esac;' '};'
ksh93: eval: syntax error: `(' unexpected
And dash
:
$ eval $(cat foo.sh)
+ cat foo.sh
+ eval foo() { somevar=1; case somevar in aha) echo "something" ;; a() echo "other" ;; esac; };
dash: 1: eval: Syntax error: "(" unexpected (expecting ")")
Only the zsh
would handle this as it does not perform the globbing:
$ eval $(cat foo.sh)
+zsh:2> cat foo.sh
+zsh:2> eval 'foo()' '{' 'somevar=1;' case somevar in 'aha)' echo '"something"' ';;' '*)' echo '"other"' ';;' 'esac;' '};'
The correct way to handle this would be to source the foo.sh
script:
. ./foo.sh
There is really no reason to use eval "$(cat foo.sh)"
as far as I can see.
This is also a code injection vulnerability:
$ touch '*) echo "hello" ;; *)'
$ eval $(cat foo.sh)
$ declare -f foo
foo ()
{
somevar=1;
case somevar in
aha)
echo "something"
;;
*)
echo "hello"
;;
*)
echo "other"
;;
esac
}
Another way of breaking this command easily without creating a specially named file, is to set the IFS
variable to a set of characters other than the default:
$ IFS=';{} '
+ IFS=';{} '
$ eval $(cat foo.sh)
++ cat foo.sh
+ eval 'foo()' '
' somevar=1 '
' case somevar 'in
' 'aha)' echo '"something"' '' '
' '*)' echo '"other"' '' '
' esac '
' ''
bash: syntax error near unexpected token `somevar=1'
This breaks it because of the word-splitting step rather than the file globbing step in the evaluation of the arguments to eval
. With IFS=';{} '
, each of those characters would be used to split the text in foo.sh
up into words (and those characters would then be removed from the string).
Not even zsh
would be immune to this:
$ IFS=';{} '
+zsh:2> IFS=';{} '
$ eval $(cat foo.sh)
+zsh:3> cat foo.sh
+zsh:3> eval 'foo()' $'n' 'somevar=1' $'n' case somevar $'inn' 'aha)' echo '"something"' '' $'n' '*)' echo '"other"' '' $'n' esac $'n' '' ''
zsh: parse error near `)'
Related:
- Security implications of forgetting to quote a variable in bash/POSIX shells
- When is double-quoting necessary?
- Why does my shell script choke on whitespace or other special characters?
This is neither strange nor a bug in bash
(it does seem to be a bug in /usr/share/modules/init/bash
though). You are using an unquoted command substitution together with eval
. The string that is the result of the command substitution will, since it is unquoted, undergo word splitting and filename expansion (globbing). The *)
in the code matches the filename a()
, so it is replace by this filename in the filename expansion stage.
Running your example under set -x
highlights this:
$ eval $(cat foo.sh)
++ cat foo.sh
+ eval 'foo()' '{' 'somevar=1;' case somevar in 'aha)' echo '"something"' ';;' 'a()' echo '"other"' ';;' 'esac;' '};'
bash: syntax error near unexpected token `('
The same thing in the yash
shell:
$ eval $(cat foo.sh)
+ cat foo.sh
+ eval 'foo()' '{' 'somevar=1;' case somevar in 'aha)' echo '"something"' ';;' 'a()' echo '"other"' ';;' 'esac;' '};'
eval:1: syntax error: `)' is missing
eval:1: syntax error: `esac' is missing
eval:1: syntax error: `}' is missing
And with ksh93
:
$ eval $(cat foo.sh)
+ cat foo.sh
+ eval 'foo()' '{' somevar='1;' case somevar in 'aha)' echo '"something"' ';;' 'a()' echo '"other"' ';;' 'esac;' '};'
ksh93: eval: syntax error: `(' unexpected
And dash
:
$ eval $(cat foo.sh)
+ cat foo.sh
+ eval foo() { somevar=1; case somevar in aha) echo "something" ;; a() echo "other" ;; esac; };
dash: 1: eval: Syntax error: "(" unexpected (expecting ")")
Only the zsh
would handle this as it does not perform the globbing:
$ eval $(cat foo.sh)
+zsh:2> cat foo.sh
+zsh:2> eval 'foo()' '{' 'somevar=1;' case somevar in 'aha)' echo '"something"' ';;' '*)' echo '"other"' ';;' 'esac;' '};'
The correct way to handle this would be to source the foo.sh
script:
. ./foo.sh
There is really no reason to use eval "$(cat foo.sh)"
as far as I can see.
This is also a code injection vulnerability:
$ touch '*) echo "hello" ;; *)'
$ eval $(cat foo.sh)
$ declare -f foo
foo ()
{
somevar=1;
case somevar in
aha)
echo "something"
;;
*)
echo "hello"
;;
*)
echo "other"
;;
esac
}
Another way of breaking this command easily without creating a specially named file, is to set the IFS
variable to a set of characters other than the default:
$ IFS=';{} '
+ IFS=';{} '
$ eval $(cat foo.sh)
++ cat foo.sh
+ eval 'foo()' '
' somevar=1 '
' case somevar 'in
' 'aha)' echo '"something"' '' '
' '*)' echo '"other"' '' '
' esac '
' ''
bash: syntax error near unexpected token `somevar=1'
This breaks it because of the word-splitting step rather than the file globbing step in the evaluation of the arguments to eval
. With IFS=';{} '
, each of those characters would be used to split the text in foo.sh
up into words (and those characters would then be removed from the string).
Not even zsh
would be immune to this:
$ IFS=';{} '
+zsh:2> IFS=';{} '
$ eval $(cat foo.sh)
+zsh:3> cat foo.sh
+zsh:3> eval 'foo()' $'n' 'somevar=1' $'n' case somevar $'inn' 'aha)' echo '"something"' '' $'n' '*)' echo '"other"' '' $'n' esac $'n' '' ''
zsh: parse error near `)'
Related:
- Security implications of forgetting to quote a variable in bash/POSIX shells
- When is double-quoting necessary?
- Why does my shell script choke on whitespace or other special characters?
edited Feb 18 at 13:15
answered Feb 17 at 17:43
KusalanandaKusalananda
132k17252414
132k17252414
1
Thanks. I learned a bit more about bash again. :) (In particular, "set -f" can fix the error too by disable filename expansion.) I also finally upgraded to Ubuntu 18.10, which fixed the environment-modules error.
– KIAaze
Feb 18 at 22:06
add a comment |
1
Thanks. I learned a bit more about bash again. :) (In particular, "set -f" can fix the error too by disable filename expansion.) I also finally upgraded to Ubuntu 18.10, which fixed the environment-modules error.
– KIAaze
Feb 18 at 22:06
1
1
Thanks. I learned a bit more about bash again. :) (In particular, "set -f" can fix the error too by disable filename expansion.) I also finally upgraded to Ubuntu 18.10, which fixed the environment-modules error.
– KIAaze
Feb 18 at 22:06
Thanks. I learned a bit more about bash again. :) (In particular, "set -f" can fix the error too by disable filename expansion.) I also finally upgraded to Ubuntu 18.10, which fixed the environment-modules error.
– KIAaze
Feb 18 at 22:06
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%2f501188%2ffile-with-parentheses-brackets-in-working-directory-causes-eval-error%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
It appears this has already been reported as a bug (and fixed) to the environment-modules package here: github.com/cea-hpc/modules/issues/220 and adding single/double quotes fixes the error. My test script could be simplified to "echo *". But why? Bash and its expansion system still confuses me... I was considering updating my question or answering, but I would really appreciate a clear explanation to what exactly is happening.
– KIAaze
Feb 17 at 17:21
I'm tempted to mark this as a duplicate of Why does my shell script choke on whitespace or other special characters?
– ilkkachu
Feb 17 at 18:01