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 useenv
instead 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
1483
1483
1
You can useenv
instead ofeval
, which IIRC is more secure, but slower.
– wjandrea
Dec 20 at 18:37
add a comment |
1
You can useenv
instead 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=bar
isn't a variable assignment (whatever be the value of$foo
), because$foo=bar
doesn't fit thename=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
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=bar
isn't a variable assignment (whatever be the value of$foo
), because$foo=bar
doesn't fit thename=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
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=bar
isn't a variable assignment (whatever be the value of$foo
), because$foo=bar
doesn't fit thename=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
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=bar
isn't a variable assignment (whatever be the value of$foo
), because$foo=bar
doesn't fit thename=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
add a comment |
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 thename=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
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
env
instead ofeval
, which IIRC is more secure, but slower.– wjandrea
Dec 20 at 18:37