Есть ли разница между добавлением пары имя-значение к команде и использованием env в bash?

19

Допустим, я призываю A=B commandи env A=B commandв bash. Есть ли ситуация, когда между обоими вызовами может быть разница?

Карл Рихтер
источник

Ответы:

26

Они служат одной и той же цели (передайте данные env vars команде). Однако есть несколько заметных отличий:

A=B command

является оболочкой (Bourne / POSIX / rc)

Например, вы можете сделать:

A=B find . -exec cmd '{}' +

или:

find . -exec env A=B cmd '{}' +

Но вы не можете сделать:

find . -exec A=B cmd '{}' +

Потому findчто не вызывает оболочку для запуска этой команды.

С другой стороны, envбудучи внешней командой, вы не можете делать:

f() { ...; }
env A=B f

или:

env A=B eval '...'

Также:

A=B cmd

работает только с env vars, которые являются допустимыми именами переменных оболочки . Вам нужно envлюбое другое имя env var:

env 'my var=foo' cmd...

bashсбрасывает _переменную:

bash-4.3$ _=xxx env | grep '^_='
_=/usr/bin/env
bash-4.3$ env _=xxx env | grep '^_='
_=xxx

В zsh, ARGV0и STTYимеет особое значение в этом контексте:

STTY=-echo cat

Работает catс echoотключенным терминалом . И:

ARGV0=foo cmd

работает cmdс fooего argv[0].

Если вы не хотите эту специальную обработку, вы должны использовать env.

Обратите внимание, что sudoподдерживает:

sudo A=B cmd

Он не использует оболочку или envдля этого. Это делает это само по себе.

Он может передавать переменные с любым именем, кроме тех, которые начинаются с -.

Присваивание является конструкцией оболочки, тогда как знак равенства в аргументе envне имеет специального значения для оболочки, поэтому A=$B cmdбезопасен, тогда как env A="$B" cmd(или sudo A="$B" cmd) требует двойных кавычек.

A=B cmdСинтаксис поддерживается только в оболочках Bourne и rcсемей (не esхотя). В оболочках cshили fishсемьях, например, вы должны прибегнуть к env.

Стефан Шазелас
источник