Recently I noticed we have 3 options to set environment variables:

  1. export envVar1=1
  2. setenv envVar2=2
  3. env envVAr3=3

If there are other ways, please enlighten us.

When should I prefer one over the other? Please suggest guidelines.

As for shell compatibility, which is the most expansive (covers more shell dialects)?

I already noticed this answer but I wish to expand the question with env and usage preference guidelines.


export VARIABLE_NAME='some value' is the way to set an environment variable in any POSIX-compliant shell (sh, dash, bash, ksh, etc.; also zsh). If the variable already has a value, you can use export VARIABLE_NAME to make it an environment variable without changing its value.

Pre-POSIX Bourne shells did not support this, which is why you'll see scripts that avoid export VARIABLE_NAME='some value' and use VARIABLE_NAME='some value'; export VARIABLE_NAME instead. But pre-POSIX Bourne shells are extremely rare nowadays.

setenv VARIABLE_NAME='some value' is the csh syntax to set an environment variable. Unlike in sh, setenv VARIABLE_NAME. setenv does not exist in sh, and csh is extremely rarely used in scripts and has been surpassed by bash for interactive use for the last 20 years (and zsh for even longer), so you can forget about it unless you encounter it.

The env command is very rarely useful except in shebang lines. When invoked without arguments, it displays the environment, but export does it better (sorted, and often quoted to disambiguate newlines in values from newlines that separate values. When invoked with arguments, it runs a command with extra environment variables, but the same command without env also works (VAR=value mycommand runs mycommand with VAR set to value, just like env VAR=value mycommand). The reason env is useful in shebang line is that it performs PATH lookup, and it happens to not do anything else when invoked with a command name. The env command can be useful to run a command with only a few environment variables with -i, or without parameters to display the environment including variables with invalid names that the shell doesn't import.


Setting a variable like VAR='asdf' leaves environment unmodified, meaning that the programs you launch in the same session will know nothing about VAR and will be unable to access it. You want this behaviour when writing shell scripts.

export, on the other hand, is a bash builtin that modifies the environment thus making the exported variable visible for child processes spawned in the current session. You can achieve the same by running VAR='asdf' %program_name%.

env is not a builtin, but a program by itself. On the surface it works exactly like when you VAR='asdf' %program_name%, but at the lower level things get a little more complicated. First, the env gets launched. It modifies environment, then executes the command with given arguments. The same behaviour you can acheive in your own code by using exec(3) system call.

setenv is just export in csh-family shells, as stated in your answer.

  • 1
    In modern shells, VAR=asdf does update the environment if VAR was already in the environment. (This wasn't true in the original Bourne shell.) – Gilles Jun 3 '17 at 22:32

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.