env Command: Running Commands with a Modified Environment
What is the env command?
Conclusion:
envis a coreutils tool that runs a command with a modified environment. Written asenv VAR=value command, it lets you run one command in a different environment without polluting your current shell.
env has two main jobs:
- Set environment variables temporarily and run a command (
env LANG=C datechanges a variable for that one invocation) - List the current environment when run with no arguments (same as
printenv)
It is also widely used in a script's shebang line (#!/usr/bin/env python3) to locate an interpreter via PATH.
Environment for this article
- GNU coreutils
env(Ubuntu / Debian / RHEL-based and other common Linux distributions) - Some options (
-C/-S) depend on the coreutils version. See below.
Why use env VAR=value?
Conclusion: Because you want a variable to apply to one command only, without making it permanent and without polluting the current shell.
exportpersists;envis one-shot.
There are several ways to run a command with a changed variable. Know the differences.
# (1) Shell built-in temporary assignment (no env) $ LANG=C date # (2) Temporary assignment via env $ env LANG=C date # (3) export (affects every later command, persistent) $ export LANG=C $ date
Forms (1) and (2) both change the variable for that single invocation. Form (3), export, keeps the change for every command you run afterward. When you want "just this once" or "do not leave the setting behind," pick (1) or (2).
How (1) and (2) differ
LANG=C dateis shell syntax (a prefix assignment). The shell interprets it.env LANG=C datelaunches the separateenvexecutable, which builds the environment in a child process and thenexecsdate.
For interactive use the result is the same. env becomes necessary when no shell is involved: shebang lines, arguments to exec-family APIs, or starting from an empty environment.
Set a variable temporarily and run
Conclusion: Write
env NAME=value command args.... List multiple variables separated by spaces.
# Show the date with the time zone temporarily set to UTC $ env TZ=UTC date # Force the C locale to get English messages (handy for log investigation) $ env LANG=C ls /nonexistent
ls: cannot access '/nonexistent': No such file or directory
To set several variables at once, list them in sequence:
$ env LANG=C LC_ALL=C TZ=UTC ./myscript.sh
Isolating locale-related errors
In a non-English environment, error messages may be translated and hard to search for. Pinning messages to English with env LANG=C command makes searching and filing issues easier.
Run with an empty environment (env -i)
Conclusion:
env -istarts the command with all inherited environment variables removed. It is ideal for isolating "works only on my machine" problems.
# Check what remains (almost nothing) $ env -i env
With -i (--ignore-environment), even PATH is not inherited. So under -i you must specify the command by absolute path or pass the variables you need explicitly.
# PATH is gone, so pass only the variables you need $ env -i PATH=/usr/bin:/bin LANG=C ./myscript.sh
Under env -i, variables such as HOME, PATH, and LANG are undefined. If a script depends on them, it may misbehave. Passing only the variables you actually need is the safe pattern.
Run without a specific variable (env -u)
Conclusion:
env -u NAMEremoves only that variable before running the command. Unlike-i, which clears everything, use it to disable a single variable.
# Temporarily disable proxy settings and test the connection $ env -u http_proxy -u https_proxy curl https://example.com
-u (--unset) can be repeated for each variable. It lets you test the hypothesis "maybe this variable is the culprit" without editing any config file.
Run in a different directory (env -C)
Conclusion:
env -C DIR commandchanges to the given directory before running the command. It packscd DIR && commandinto one line without a subshell.
$ env -C /var/log tail -n 20 syslog
-C (--chdir) is available in coreutils 8.28 and later. It is unavailable in older environments. Check with env --version (see below).
Using /usr/bin/env in a shebang
Conclusion: A shebang like
#!/usr/bin/env python3finds the interpreter throughPATH. It avoids hardcoding an absolute interpreter path, making the script portable.
#!/usr/bin/env python3
print("hello")Writing #!/usr/bin/python3 directly breaks on systems where Python lives elsewhere (/usr/local/bin, a virtualenv, and so on). #!/usr/bin/env python3 searches PATH, so it uses the first python3 found in that user's environment.
#!/usr/bin/env -S python3 -u
To pass arguments to the interpreter in a shebang line, use -S (--split-string). A shebang normally allows only one argument; -S splits the string into multiple arguments.
-S requires coreutils 8.30 or later. Support also differs on macOS (BSD env), so verify the target environment before using it in distributed scripts.
env vs printenv vs set
Conclusion:
envwith no arguments lists environment variables only. Usesetfor all variables including shell variables, andprintenv NAMEfor a single one.
| Goal | Command |
|---|---|
| List environment variables | env or printenv |
| Show one environment variable | printenv PATH (env alone cannot filter) |
| Include shell variables too | set (bash built-in) |
| Set temporarily and run | env VAR=val cmd |
Passing a single argument like env PATH does not print the value: env treats it as a command name and reports "No such file or directory." To see just the value, use printenv PATH or echo "$PATH".
Troubleshooting
Conclusion: The common stumbles with
envare "no PATH after-i" and "-C/-Sunavailable on an old system." A version check resolves most of them.
"env: '...': No such file or directory"
env treats the first argument without an = as a command name. You get this error from env LANG C date (a missing =) or env PATH (trying to read a value). Make sure the form is NAME=value.
Command not found after env -i
-i also clears PATH. Either specify PATH explicitly as in env -i PATH=/usr/bin:/bin command, or give the command by absolute path.
# Check the env version (to decide whether -C / -S are available) $ env --version | head -1
env (GNU coreutils) 9.4