What is the difference between the command
$ env FOO=bar baz
and
$ FOO=bar baz
What effect does env
have?
What is the difference between the command
$ env FOO=bar baz
and
$ FOO=bar baz
What effect does env
have?
They are functionally equivalent.
The main difference is that env FOO=bar baz
involves invoking an intermediary process between the shell and baz
, where as with FOO=bar baz
the shell directly invokes baz
.
So in that regard, FOO=bar baz
is preferred.
The only situations I find myself using env FOO=bar
in is where I have to pass a command to another command.
As a specific example, lets say I have a wrapper script that performs some modifications of the environment, and then calls exec
on the command that was passed to it, such as:
#!/bin/bash
FOO=bob
some stuff
exec "$@"
If you execute it as myscript FOO=bar baz
, the exec
will throw an error as exec FOO=bar baz
is invalid.
Instead you call it as myscript env FOO=bar baz
which gets executed as exec env FOO=bar baz
, and is perfectly valid.
FOO=bar exec baz
though, so you don't need env
in your last point.
– Stéphane Chazelas
May 15 '14 at 19:25
sudo FOO=bar baz
to pass environment variables without the need for env
.
– Michael Miller
May 15 '14 at 19:27
FOO=bar
in the script. If FOO
isn't always bar
, I don't want to hard code it, and instead pass it in.
– phemmer
May 15 '14 at 19:27
exec
, such as FOO=bar exec baz
.
– phemmer
May 15 '14 at 19:28
sudo
did and it would be a good example. My mistake :-(
– phemmer
May 15 '14 at 19:30
exec
.
– Stéphane Chazelas
May 15 '14 at 19:34
exec
automatically if it looks reasonable to do so.
– Aaron Davies
May 16 '14 at 17:22
In this particular example, there is no effective difference, assuming your shell is a POSIX-compatible shell, and assuming baz
is an executable and not a shell builtin.
If your shell is not a POSIX-compatible shell, for example csh
or tcsh
, the syntax
FOO=bar baz
does not work, and there is no equivalent shell syntax. For those shells, the env
command is the only way to override or inject environment variables for a single command.
If baz
is a shell builtin, let's say fc
for example, then env
will not give the same results, because env
is executing a new process instead of being run directly by the command shell. Moreover, there is no fc
executable, it can only be run as a shell builtin because of the way it interacts with the shell environment, and so env
will never work with a builtin like fc
.
In addition, env
offers the -i
option, which allows you to start a command in an empty environment with only a specified set of environment variables. So env
can be very useful for starting processes in sanitized environments, for example
env -i HOME=/tmp/homedir "PATH=`getconf PATH`" "TERM=$TERM" FOO=bar baz
tcsh
I would write (setenv FOO bar; baz)
to get the equivalent function.
– Barmar
May 21 '14 at 19:53
In addition to what has already been said
VAR=value cmd args > redirs
being a shell (Bourne/POSIX) feature, you're limited in the name of the environment variables you pass to cmd
. They have to be valid shell variable names and must not be read-only or special variables to the shell.
For instance, you cannot do:
1=foo cmd
Or
+++=bar cmd
bash
doesn't allow you to do:
SHELLOPTS=xtrace cmd
While you can do:
env 1=foo cmd
env +++=bar cmd
env '=baz' cmd
(not that you want or should want to do that). Or:
env SHELLOPTS=xtrace cmd
(I sometimes need to do that).
Note that with env
you still cannot pass an environment variable string that doesn't contain a =
(not that you would want to do that either).
One use of env
is to allow $PATH
searching of executables in shebang lines (because env
considers the $PATH
when searching for the executable). This is useful if the executable you want to invoke may be in different places on different machines. For example,
#!/usr/bin/env perl
in the first line of a script with executable bit set will execute this script with Perl no matter whether it is installed in /usr/bin/perl
or in /usr/local/bin/perl
or in a completely different place, as long as the directory is in the path.
Of course that path search comes with an added risk, but then, the risk is not larger than if you had explicitly written perl yourscript.pl
, which also looks up perl in the search path.
Another time when env
is really useful is if you want to control the environment completely. I run a server program (Informix, in case you can't guess) whose environment I want to control completely. I run it using env
at the end of a script which sets a bunch of variables to the correct values:
env -i HOME="$IXD" \
INFORMIXDIR="$IXD" \
INFORMIXSERVER="$IXS" \
${IXC:+INFORMIXCONCSMCFG="$IXC"} \
${IXH:+INFORMIXSQLHOSTS="$IXH"} \
IFX_LISTEN_TIMEOUT=3 \
ONCONFIG="onconfig.$IXS" \
PATH="/bin:/usr/bin:$IXD/bin" \
SHELL=/bin/ksh \
TZ=UTC0 \
$ONINIT "$@"
The -i
option zaps the existing environment. The subsequent VAR=value
options set the environment variables that I want set; the name of the program is in $ONINIT
, and any command line arguments are passed through verbatim with "$@"
.
The ${IXH:+INFORMIXSQLHOSTS="$IXH"}
construct only passes INFORMIXSQLHOSTS="$IXH"
to env
if $IXH
is set to a non-empty value.
env
is an executable from GNU Coreutils, NOT a shell builtin
$ type env
env is hashed (/usr/bin/env)
$ which env
/usr/bin/env
$ env FOO=bar baz
:
• bash
calls env
, then env
sets FOO to bar and calls baz
$ FOO=bar baz
:
• bash
sets FOO to bar and calls baz
directly
demo of this key difference:
$ FOO=bar /proc/self/exe --version
GNU bash, version 5.1.4(1)-release (x86_64-pc-linux-gnu)
Copyright (C) 2020 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.
$ env FOO=bar /proc/self/exe --version
env (GNU coreutils) 8.32
Copyright (C) 2020 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <https://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.
Written by Richard Mlynarik, David MacKenzie, and Assaf Gordon.