¿Hay alguna diferencia entre anteponer un par nombre-valor a un comando y usar env en bash?

19

Digamos que invoco A=B commandy env A=B commanden bash. ¿Hay alguna situación en la que pueda haber una diferencia entre ambas invocaciones?

Karl Richter
fuente

Respuestas:

26

Sirven para el mismo propósito (pasar los envios dados al comando). Sin embargo, algunas diferencias notables:

A=B command

es una construcción de shell (Bourne / POSIX / rc).

Por ejemplo, puedes hacer:

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

o:

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

Pero no puedes hacer:

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

Porque findno está invocando un shell para ejecutar ese comando.

Por otro lado, al envser un comando externo, no puedes hacer:

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

o:

env A=B eval '...'

También:

A=B cmd

funciona solo con env que son nombres de variables de shell válidos . Necesita envcualquier otro nombre de env env:

env 'my var=foo' cmd...

bashrestablece la _variable:

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

En zsh, ARGV0y STTYtienen significados especiales en ese contexto:

STTY=-echo cat

Se ejecuta catcon terminal echodeshabilitado. Y:

ARGV0=foo cmd

corre cmdcon foocomo es argv[0].

Si no desea ese procesamiento especial, debe usarlo env.

Tenga en cuenta que sudoadmite:

sudo A=B cmd

No está usando el shell ni envpara hacer eso. Lo hace solo.

Puede pasar variables con cualquier nombre excepto aquellos que comienzan con -.

La asignación es una construcción de shell, mientras que un signo igual en el argumento de envno tiene un significado especial para el shell, por lo que A=$B cmdes seguro, mientras que env A="$B" cmd(o sudo A="$B" cmd) requieren comillas dobles.

La A=B cmdsintaxis solo es compatible con los shells de Bourne y las rcfamilias ( esaunque no ). En los depósitos de las familias csho fish, por ejemplo, debe recurrir a env.

Stéphane Chazelas
fuente