Apakah ada perbedaan antara menambahkan pasangan nama-nilai ke suatu perintah dan menggunakan env di bash?

19

Katakanlah saya memanggil A=B commanddan env A=B commandmasuk bash. Apakah ada situasi di mana mungkin ada perbedaan antara kedua invokations?

Karl Richter
sumber

Jawaban:

26

Mereka melayani tujuan yang sama (meneruskan perintah yang diberikan kepada perintah). Namun beberapa perbedaan penting:

A=B command

adalah konstruksi shell (Bourne / POSIX / rc).

Misalnya, Anda dapat melakukan:

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

atau:

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

Tetapi Anda tidak bisa melakukan:

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

Karena findtidak meminta shell untuk menjalankan perintah itu.

Di sisi lain, envmenjadi perintah eksternal, Anda tidak dapat melakukan:

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

atau:

env A=B eval '...'

Juga:

A=B cmd

hanya bekerja dengan env vars yang merupakan nama variabel shell yang valid . Anda memerlukan envnama env var lainnya:

env 'my var=foo' cmd...

bashme-reset _variabel:

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

Di zsh, ARGV0dan STTYmemiliki makna khusus dalam konteks itu:

STTY=-echo cat

Berjalan catdengan terminal echodinonaktifkan. Dan:

ARGV0=foo cmd

berjalan cmddengan foosebagai yang argv[0].

Jika Anda tidak ingin pemrosesan khusus itu, Anda harus menggunakannya env.

Catatan yang sudomendukung:

sudo A=B cmd

Itu tidak menggunakan shell atau envuntuk melakukan itu. Itu melakukannya dengan sendirinya.

Itu bisa melewati variabel dengan nama apa pun kecuali yang dimulai dengan -.

Tugas adalah konstruksi shell sedangkan tanda sama dalam argumen envtidak memiliki arti khusus untuk shell, jadi A=$B cmdaman sedangkan env A="$B" cmd(atau sudo A="$B" cmd) membutuhkan tanda kutip ganda.

The A=B cmdsintaks hanya didukung dalam cangkang dari Bourne dan rckeluarga (tidak esmeskipun). Dalam kerang cshatau fishkeluarga misalnya, Anda harus menggunakan env.

Stéphane Chazelas
sumber