Existe uma diferença entre anexar um par nome-valor a um comando e usar env no bash?

19

Digamos que eu chame A=B commande env A=B commandentre bash. Existe alguma situação em que possa haver uma diferença entre as duas invocações?

Karl Richter
fonte

Respostas:

26

Eles servem ao mesmo propósito (passe os envios fornecidos ao comando). No entanto, algumas diferenças notáveis:

A=B command

é uma construção shell (Bourne / POSIX / rc).

Por exemplo, você pode fazer:

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

ou:

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

Mas você não pode fazer:

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

Porque findnão está invocando um shell para executar esse comando.

Por outro lado, envsendo um comando externo, você não pode fazer:

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

ou:

env A=B eval '...'

Além disso:

A=B cmd

funciona apenas com env vars que são nomes válidos de variáveis ​​de shell . Você precisa envde qualquer outro nome de var env:

env 'my var=foo' cmd...

bashredefine a _variável:

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

Em zsh, ARGV0e STTYtêm significados especiais nesse contexto:

STTY=-echo cat

Funciona catcom o terminal echodesativado. E:

ARGV0=foo cmd

corre cmdcom foocomo seu argv[0].

Se você não quiser esse processamento especial, precisará usar env.

Observe que sudosuporta:

sudo A=B cmd

Não está usando o shell ou envpara fazer isso. Faz isso por si só.

Pode passar variáveis ​​com qualquer nome, exceto aquelas que começam com -.

A atribuição é uma construção de shell, enquanto um sinal de igual no argumento de envnão tem significado especial para o shell, portanto, A=$B cmdé seguro enquanto env A="$B" cmd(ou sudo A="$B" cmd) exige aspas duplas.

A A=B cmdsintaxe é suportada apenas nas conchas dos Bourne e das rcfamílias ( esembora não ). Em conchas cshou fishfamílias, por exemplo, você precisa recorrer env.

Stéphane Chazelas
fonte