The following three shell snippets are equivalent (as in, they accomplish the same thing, and you have to dig in to observe any different effect):
env COLUMNS=%s ps …
COLUMNS=%s ps …
(export COLUMNS=%s; ps …)
All of them set the environment variable
COLUMNS to the value
%s for the invocation of the
ps command. In the shell, the value of
COLUMNS, if any, remains the same as before. The first snippet accomplishes this effect through the external program
env, the second using pure shell syntax, the third through the
export shell builtin combined with the
(…) subshell construct.
This is different from
export COLUMNS=%s; ps …
which would set the environment variable
COLUMNS in a way that remains in effect in the remainder of the script, and from
COLUMNS=%s; ps …
which unlike the others sets only a shell variable (which
ps won't see), but does not export
COLUMNS to the environment. (However, if
COLUMNS was already present in the environment, it is set to
env may look useless, but it exists
- because it's older than the
VAR=value command shell construct;
- because it's useful in other cases, for example when a program starts another program without going through a shell and you want to set a few environment variables;
- because it can work systems that have a different shell (e.g. in csh, or on Windows), as long as the
env command is available and in the PATH.
All the constructs mentioned here work in any Bourne/POSIX-style shell (sh, ash, bash, ksh, zsh, …), except a few antique Bourne shell versions that you're unlikely to ever encounter (and that have never been ported to Linux or OSX).
COLUMNS should be a number;
ps ignores it if it isn't numeric. Zsh even refuses to set
COLUMNS to a non-numeric value, because it declares
COLUMNS as a numeric variable by default. In the program you're quoting,
%s will be replaced by a number before the string is used as a shell command.