Czy istnieje różnica między przygotowaniem pary nazwa-wartość do polecenia a użyciem env w bash?

19

Powiedzmy, wzywam A=B commandi env A=B commandw bash. Czy jest jakaś sytuacja, w której może istnieć różnica między tymi dwoma wywołaniami?

Karl Richter
źródło

Odpowiedzi:

26

Służą temu samemu celowi (przekazują podane zmienne env do polecenia). Jednak kilka znaczących różnic:

A=B command

jest konstrukcją powłoki (Bourne / POSIX / rc).

Na przykład możesz wykonać:

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

lub:

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

Ale nie możesz zrobić:

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

Ponieważ findnie wywołuje powłoki, aby uruchomić to polecenie.

Z drugiej strony, envbędąc poleceniem zewnętrznym, nie możesz wykonać:

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

lub:

env A=B eval '...'

Również:

A=B cmd

działa tylko z zmiennymi env, które są poprawnymi nazwami zmiennych powłoki . Potrzebujesz envinnej nazwy env var:

env 'my var=foo' cmd...

bashresetuje _zmienną:

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

W zsh, ARGV0i STTYmają specjalne znaczenie w tym kontekście:

STTY=-echo cat

Działa catz echowyłączonym terminalem . I:

ARGV0=foo cmd

biegnie cmdz foojak jego argv[0].

Jeśli nie chcesz tego specjalnego przetwarzania, musisz go użyć env.

Uwaga sudo: obsługuje:

sudo A=B cmd

Nie używa powłoki ani envtego nie robi. Robi to samo.

Może przekazywać zmienne o dowolnej nazwie oprócz tych rozpoczynających się od -.

Przypisanie jest konstrukcją powłoki, podczas gdy znak równości w argumencie argumentu envnie ma specjalnego znaczenia dla powłoki, więc A=$B cmdjest bezpieczny, podczas gdy env A="$B" cmd(lub sudo A="$B" cmd) wymagają podwójnych cudzysłowów.

A=B cmdSkładnia jest obsługiwana tylko w muszlach Bourne i rcrodzin (nie eschociaż). Na przykład w muszlach cshlub fishrodzinach musisz uciekać się env.

Stéphane Chazelas
źródło