45

What is the command env ls -al doing?

I had a Linux test and there was question: "How to run command directly, but not its alias?"
I knew that there exists solution like prefixing command with some special symbol, but I forgot it. Now I know that it is \. (read from this post).

But I also remember that somewhere I read that to get rid of alias we can prefix a command with env. I did it and it seems works, but my answer was qualified as wrong. I read info and man on env, but didn't understood too much.

What is env doing and exactly in env <command> without any arguments for env itself?

ALZ
  • 931
  • As a note, 3 ways of doing this that I can think of are env <command>, command <command>, and \<command>. In my opinion, if some test said env <command> is invalid, then that test is broken. – phemmer Dec 03 '13 at 13:59
  • @Patrick: It is not broken because as Chris said, there could be an alias on command or env which would make \\ the only acceptable answer. – Pierre Arlaud Dec 03 '13 at 14:41
  • 1
    @ArlaudPierre and \\ isn't defined in posix (as an alias escape), so it's not portable. So it's no more acceptable than the others. – phemmer Dec 03 '13 at 14:46
  • @Patrick: true, true. Now we'd have to know the exact perimeter of the test to say that. But in any case, find that the "env" answer is not an acceptable one isn't very honest, I'd have to agree with you on that. – Pierre Arlaud Dec 03 '13 at 14:50
  • Guys, test was verified by human too (LPI-certified ex-sysadmin, which teaching now others Linux) :) I complained to verifier, went to man and didn't understood what env exactly doing. After this post - it's clear and my answer was reviewed (accepted). Thanks to all! – ALZ Dec 03 '13 at 16:33
  • @Patrick A backslash does avoid alias expansion in all POSIX shells: only unquoted words are subject to alias substitution. Other ways include l\s, "l"s, ls'', ls$(), … – Gilles 'SO- stop being evil' Dec 03 '13 at 22:41

2 Answers2

47

This command

env name=value name2=value2 program and args

runs the command program and args with an environment formed by extending the current environment with the environment variables and values designated by name=value and name2=value2. If you do not include any arguments like name=value, then the current environment is passed along unmodified.

The key thing that happens with respect to aliases is that env is an external command, so it has no “knowledge” of aliases: aliases are a shell construct that are not part of the normal process model and have no impact on programs that are directly run by non-shell programs (like env). env simply passes the program and arguments to an exec call (like execvp, which will search the PATH for program).

Basically, using env like this is a (mostly) shell-independent way of avoiding aliases, shell functions, shell builtin commands, and any other bits of shell functionality that might replace or override command-position arguments (i.e. program names)—unless, of course, env is an alias, or shell function! If you are worried about env being an alias, you could spell out the full path (e.g. /usr/bin/env, though it may vary).

Chris Johnsen
  • 20,101
  • why does a command such: env MYVAR=3 echo $MYVAR does not display anything? – piertoni May 19 '20 at 08:28
  • 2
    @piertoni the $MYVAR is interpreted by your shell when you run the command, it's not deferred until env runs echo. Try eg. env MYVAR=3 sh -c 'echo $MYVAR' – detly Sep 09 '20 at 05:00
29

Another important use of env (apart from circumventing command alias lookup) is that it searches the PATH for the command. This is of importance where absolute paths are required, but vary from system to system.

For example, beginning a Bash script with #!/bin/bash is okay, whereas #!bash isn't, despite of /bin being included in the PATH on every reasonable system.

I frequently encountered this in Python programs, which usually begin with #!/usr/bin/env python to avoid specifying the full, system-dependent path of the python executable (note, however, that it still requires that env resides in /usr/bin, this is however far more common than the location of the python binary).

misberner
  • 391