Why can I not use variables as prefix to a command to set environment variables?
Normally, it is possible to set an environment variable for a command by prefixing it like so:
hello=hi bash -c 'echo $hello'
I also know that we can use a variable to substitute any part of a command invocation like the following:
$ cmd=bash
$ $cmd -c "echo hi" # equivalent to bash -c "echo hi"
I was very surprised to find out that you cannot use a variable to prefix a command to set an environment variable. Test case:
$ prefix=hello=hi
$ echo $prefix # prints hello=hi
$ $prefix bash -c 'echo $hello'
hello=hi: command not found
Why can I not set the environment variable using a variable? Is the prefix part a special part? I was able to get it working by using eval in front, but I still do not understand why. I am using bash 4.4.
bash environment-variables variable
add a comment |
Normally, it is possible to set an environment variable for a command by prefixing it like so:
hello=hi bash -c 'echo $hello'
I also know that we can use a variable to substitute any part of a command invocation like the following:
$ cmd=bash
$ $cmd -c "echo hi" # equivalent to bash -c "echo hi"
I was very surprised to find out that you cannot use a variable to prefix a command to set an environment variable. Test case:
$ prefix=hello=hi
$ echo $prefix # prints hello=hi
$ $prefix bash -c 'echo $hello'
hello=hi: command not found
Why can I not set the environment variable using a variable? Is the prefix part a special part? I was able to get it working by using eval in front, but I still do not understand why. I am using bash 4.4.
bash environment-variables variable
1
You can useenvinstead ofeval, which IIRC is more secure, but slower.
– wjandrea
Dec 20 at 18:37
add a comment |
Normally, it is possible to set an environment variable for a command by prefixing it like so:
hello=hi bash -c 'echo $hello'
I also know that we can use a variable to substitute any part of a command invocation like the following:
$ cmd=bash
$ $cmd -c "echo hi" # equivalent to bash -c "echo hi"
I was very surprised to find out that you cannot use a variable to prefix a command to set an environment variable. Test case:
$ prefix=hello=hi
$ echo $prefix # prints hello=hi
$ $prefix bash -c 'echo $hello'
hello=hi: command not found
Why can I not set the environment variable using a variable? Is the prefix part a special part? I was able to get it working by using eval in front, but I still do not understand why. I am using bash 4.4.
bash environment-variables variable
Normally, it is possible to set an environment variable for a command by prefixing it like so:
hello=hi bash -c 'echo $hello'
I also know that we can use a variable to substitute any part of a command invocation like the following:
$ cmd=bash
$ $cmd -c "echo hi" # equivalent to bash -c "echo hi"
I was very surprised to find out that you cannot use a variable to prefix a command to set an environment variable. Test case:
$ prefix=hello=hi
$ echo $prefix # prints hello=hi
$ $prefix bash -c 'echo $hello'
hello=hi: command not found
Why can I not set the environment variable using a variable? Is the prefix part a special part? I was able to get it working by using eval in front, but I still do not understand why. I am using bash 4.4.
bash environment-variables variable
bash environment-variables variable
edited Dec 20 at 3:30
Jeff Schaller
38.5k1053125
38.5k1053125
asked Dec 20 at 3:27
wbkang
1534
1534
1
You can useenvinstead ofeval, which IIRC is more secure, but slower.
– wjandrea
Dec 20 at 18:37
add a comment |
1
You can useenvinstead ofeval, which IIRC is more secure, but slower.
– wjandrea
Dec 20 at 18:37
1
1
You can use
env instead of eval, which IIRC is more secure, but slower.– wjandrea
Dec 20 at 18:37
You can use
env instead of eval, which IIRC is more secure, but slower.– wjandrea
Dec 20 at 18:37
add a comment |
2 Answers
2
active
oldest
votes
I suspect this is the part of the sequence that's catching you:
The words that are not variable assignments or redirections are expanded (see Shell Expansions). If any words remain after expansion, the first word is taken to be the name of the command and the remaining words are the arguments
That's from the Bash reference manual in the section on Simple Command Expansion.
In the cmd=bash example, no environment variables are set, and bash processes the command line up through parameter expansion, leaving bash -c "echo hi".
In the prefix=hello=hi example, there are again no variable assignments in the first pass, so processing continues to parameter expansion, resulting in a first word of hello=hi.
Once the variable assignments have been processed, they are not re-processed during command execution.
See the processing and its results under set -x:
$ prefix=hello=hi
+ prefix=hello=hi
$ $prefix bash -c 'echo $hello'
+ hello=hi bash -c 'echo $hello'
-bash: hello=hi: command not found
$ hello=42 bash -c 'echo $hello'
+ hello=42
+ bash -c 'echo $hello'
42
For a safer variation of "variable expansion" -as- "environment variables" than eval, consider wjandrea's suggestion of env:
prefix=hello=hi
env "$prefix" bash -c 'echo "$hello"'
hi
It's not strictly a command-line variable assignment, since we're using the env utility's main function of assigning environment variables to a command, but it accomplishes the same goal. The $prefix variable is expanded during the processing of the command-line, providing the name=value to env, who passes it along to bash.
3
Similarly,$foo=bar bash -c ...won't work, because$foo=barisn't a variable assignment (whatever be the value of$foo), because$foo=bardoesn't fit thename=valuepattern for variable assignment.
– muru
Dec 20 at 3:45
Looks like env is my best bet. Thanks
– wbkang
Dec 20 at 21:13
add a comment |
Because $prefix isn't an assignment. @Jeff has the longer explanation.
You could do a similar thing with a function instead:
$ prefix() { hello=hi "$@"; }
$ prefix bash -c 'echo "$hello"'
hi
...and you can even stack those, if you like:
$ foo() { foo=123 "$@"; }
$ bar() { bar=456 "$@"; }
$ foo bar bash -c 'echo "$bar $foo"'
456 123
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%2f490057%2fwhy-can-i-not-use-variables-as-prefix-to-a-command-to-set-environment-variables%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
2 Answers
2
active
oldest
votes
2 Answers
2
active
oldest
votes
active
oldest
votes
active
oldest
votes
I suspect this is the part of the sequence that's catching you:
The words that are not variable assignments or redirections are expanded (see Shell Expansions). If any words remain after expansion, the first word is taken to be the name of the command and the remaining words are the arguments
That's from the Bash reference manual in the section on Simple Command Expansion.
In the cmd=bash example, no environment variables are set, and bash processes the command line up through parameter expansion, leaving bash -c "echo hi".
In the prefix=hello=hi example, there are again no variable assignments in the first pass, so processing continues to parameter expansion, resulting in a first word of hello=hi.
Once the variable assignments have been processed, they are not re-processed during command execution.
See the processing and its results under set -x:
$ prefix=hello=hi
+ prefix=hello=hi
$ $prefix bash -c 'echo $hello'
+ hello=hi bash -c 'echo $hello'
-bash: hello=hi: command not found
$ hello=42 bash -c 'echo $hello'
+ hello=42
+ bash -c 'echo $hello'
42
For a safer variation of "variable expansion" -as- "environment variables" than eval, consider wjandrea's suggestion of env:
prefix=hello=hi
env "$prefix" bash -c 'echo "$hello"'
hi
It's not strictly a command-line variable assignment, since we're using the env utility's main function of assigning environment variables to a command, but it accomplishes the same goal. The $prefix variable is expanded during the processing of the command-line, providing the name=value to env, who passes it along to bash.
3
Similarly,$foo=bar bash -c ...won't work, because$foo=barisn't a variable assignment (whatever be the value of$foo), because$foo=bardoesn't fit thename=valuepattern for variable assignment.
– muru
Dec 20 at 3:45
Looks like env is my best bet. Thanks
– wbkang
Dec 20 at 21:13
add a comment |
I suspect this is the part of the sequence that's catching you:
The words that are not variable assignments or redirections are expanded (see Shell Expansions). If any words remain after expansion, the first word is taken to be the name of the command and the remaining words are the arguments
That's from the Bash reference manual in the section on Simple Command Expansion.
In the cmd=bash example, no environment variables are set, and bash processes the command line up through parameter expansion, leaving bash -c "echo hi".
In the prefix=hello=hi example, there are again no variable assignments in the first pass, so processing continues to parameter expansion, resulting in a first word of hello=hi.
Once the variable assignments have been processed, they are not re-processed during command execution.
See the processing and its results under set -x:
$ prefix=hello=hi
+ prefix=hello=hi
$ $prefix bash -c 'echo $hello'
+ hello=hi bash -c 'echo $hello'
-bash: hello=hi: command not found
$ hello=42 bash -c 'echo $hello'
+ hello=42
+ bash -c 'echo $hello'
42
For a safer variation of "variable expansion" -as- "environment variables" than eval, consider wjandrea's suggestion of env:
prefix=hello=hi
env "$prefix" bash -c 'echo "$hello"'
hi
It's not strictly a command-line variable assignment, since we're using the env utility's main function of assigning environment variables to a command, but it accomplishes the same goal. The $prefix variable is expanded during the processing of the command-line, providing the name=value to env, who passes it along to bash.
3
Similarly,$foo=bar bash -c ...won't work, because$foo=barisn't a variable assignment (whatever be the value of$foo), because$foo=bardoesn't fit thename=valuepattern for variable assignment.
– muru
Dec 20 at 3:45
Looks like env is my best bet. Thanks
– wbkang
Dec 20 at 21:13
add a comment |
I suspect this is the part of the sequence that's catching you:
The words that are not variable assignments or redirections are expanded (see Shell Expansions). If any words remain after expansion, the first word is taken to be the name of the command and the remaining words are the arguments
That's from the Bash reference manual in the section on Simple Command Expansion.
In the cmd=bash example, no environment variables are set, and bash processes the command line up through parameter expansion, leaving bash -c "echo hi".
In the prefix=hello=hi example, there are again no variable assignments in the first pass, so processing continues to parameter expansion, resulting in a first word of hello=hi.
Once the variable assignments have been processed, they are not re-processed during command execution.
See the processing and its results under set -x:
$ prefix=hello=hi
+ prefix=hello=hi
$ $prefix bash -c 'echo $hello'
+ hello=hi bash -c 'echo $hello'
-bash: hello=hi: command not found
$ hello=42 bash -c 'echo $hello'
+ hello=42
+ bash -c 'echo $hello'
42
For a safer variation of "variable expansion" -as- "environment variables" than eval, consider wjandrea's suggestion of env:
prefix=hello=hi
env "$prefix" bash -c 'echo "$hello"'
hi
It's not strictly a command-line variable assignment, since we're using the env utility's main function of assigning environment variables to a command, but it accomplishes the same goal. The $prefix variable is expanded during the processing of the command-line, providing the name=value to env, who passes it along to bash.
I suspect this is the part of the sequence that's catching you:
The words that are not variable assignments or redirections are expanded (see Shell Expansions). If any words remain after expansion, the first word is taken to be the name of the command and the remaining words are the arguments
That's from the Bash reference manual in the section on Simple Command Expansion.
In the cmd=bash example, no environment variables are set, and bash processes the command line up through parameter expansion, leaving bash -c "echo hi".
In the prefix=hello=hi example, there are again no variable assignments in the first pass, so processing continues to parameter expansion, resulting in a first word of hello=hi.
Once the variable assignments have been processed, they are not re-processed during command execution.
See the processing and its results under set -x:
$ prefix=hello=hi
+ prefix=hello=hi
$ $prefix bash -c 'echo $hello'
+ hello=hi bash -c 'echo $hello'
-bash: hello=hi: command not found
$ hello=42 bash -c 'echo $hello'
+ hello=42
+ bash -c 'echo $hello'
42
For a safer variation of "variable expansion" -as- "environment variables" than eval, consider wjandrea's suggestion of env:
prefix=hello=hi
env "$prefix" bash -c 'echo "$hello"'
hi
It's not strictly a command-line variable assignment, since we're using the env utility's main function of assigning environment variables to a command, but it accomplishes the same goal. The $prefix variable is expanded during the processing of the command-line, providing the name=value to env, who passes it along to bash.
edited Dec 20 at 20:12
answered Dec 20 at 3:41
Jeff Schaller
38.5k1053125
38.5k1053125
3
Similarly,$foo=bar bash -c ...won't work, because$foo=barisn't a variable assignment (whatever be the value of$foo), because$foo=bardoesn't fit thename=valuepattern for variable assignment.
– muru
Dec 20 at 3:45
Looks like env is my best bet. Thanks
– wbkang
Dec 20 at 21:13
add a comment |
3
Similarly,$foo=bar bash -c ...won't work, because$foo=barisn't a variable assignment (whatever be the value of$foo), because$foo=bardoesn't fit thename=valuepattern for variable assignment.
– muru
Dec 20 at 3:45
Looks like env is my best bet. Thanks
– wbkang
Dec 20 at 21:13
3
3
Similarly,
$foo=bar bash -c ... won't work, because $foo=bar isn't a variable assignment (whatever be the value of $foo), because $foo=bar doesn't fit the name=value pattern for variable assignment.– muru
Dec 20 at 3:45
Similarly,
$foo=bar bash -c ... won't work, because $foo=bar isn't a variable assignment (whatever be the value of $foo), because $foo=bar doesn't fit the name=value pattern for variable assignment.– muru
Dec 20 at 3:45
Looks like env is my best bet. Thanks
– wbkang
Dec 20 at 21:13
Looks like env is my best bet. Thanks
– wbkang
Dec 20 at 21:13
add a comment |
Because $prefix isn't an assignment. @Jeff has the longer explanation.
You could do a similar thing with a function instead:
$ prefix() { hello=hi "$@"; }
$ prefix bash -c 'echo "$hello"'
hi
...and you can even stack those, if you like:
$ foo() { foo=123 "$@"; }
$ bar() { bar=456 "$@"; }
$ foo bar bash -c 'echo "$bar $foo"'
456 123
add a comment |
Because $prefix isn't an assignment. @Jeff has the longer explanation.
You could do a similar thing with a function instead:
$ prefix() { hello=hi "$@"; }
$ prefix bash -c 'echo "$hello"'
hi
...and you can even stack those, if you like:
$ foo() { foo=123 "$@"; }
$ bar() { bar=456 "$@"; }
$ foo bar bash -c 'echo "$bar $foo"'
456 123
add a comment |
Because $prefix isn't an assignment. @Jeff has the longer explanation.
You could do a similar thing with a function instead:
$ prefix() { hello=hi "$@"; }
$ prefix bash -c 'echo "$hello"'
hi
...and you can even stack those, if you like:
$ foo() { foo=123 "$@"; }
$ bar() { bar=456 "$@"; }
$ foo bar bash -c 'echo "$bar $foo"'
456 123
Because $prefix isn't an assignment. @Jeff has the longer explanation.
You could do a similar thing with a function instead:
$ prefix() { hello=hi "$@"; }
$ prefix bash -c 'echo "$hello"'
hi
...and you can even stack those, if you like:
$ foo() { foo=123 "$@"; }
$ bar() { bar=456 "$@"; }
$ foo bar bash -c 'echo "$bar $foo"'
456 123
answered Dec 20 at 17:57
ilkkachu
55.5k783151
55.5k783151
add a comment |
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.
Some of your past answers have not been well-received, and you're in danger of being blocked from answering.
Please pay close attention to the following guidance:
- 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%2f490057%2fwhy-can-i-not-use-variables-as-prefix-to-a-command-to-set-environment-variables%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
1
You can use
envinstead ofeval, which IIRC is more secure, but slower.– wjandrea
Dec 20 at 18:37