Apa perbedaan antara &> dan 2> & 1

30

Ada dua bentuk redirection yaitu output standar dan standard error menjadi output standar . Tapi mana yang lebih baik? dan mengapa &>dianggap sempurna?

Saya tidak dapat menemukan perbedaannya sehingga banyak tutorial dan bahkan bash manual yang &>lebih baik!

Jadi, mengapa saya harus menggunakan &>dan tidak2>&1

Terutama menggunakan bashshell


EDIT: Terima kasih atas komentatornya

Hanya> & bekerja di csh atau tcsh

Dalam ksh hanya 2> & 1 yang berfungsi.

gunakan dash> file 2> & 1 pengalihan saja

Lalu yang mana yang digunakan untuk memastikan skrip saya kompatibel dengan sistem lain apa pun kerang yang digunakan!

Maythux
sumber
yang lebih baik adalah apa yang harus Anda lakukan. ini melakukan hal yang sangat berbeda. shell mana yang Anda gunakan?
Skaperen
@Skaperen using bash
Maythux
1
apa yang ingin kamu capai?
Skaperen
Saya hanya ingin tahu apa perbedaannya, Apa yang saya inginkan adalah tidak sama-sama tetapi saya hanya perlu tahu apakah perbedaannya sehingga sekali sudah ditentukan sebelumnya
Maythux
2
&> somewherehanyalah singkatan bash untuk > somewhere 2>&1: dalam kata-kata manual bash, mereka "setara secara symantically"
steeldriver

Jawaban:

23

Halaman manual Bash menyebutkan ada dua cara untuk mengarahkan stderr dan stdout : &> file dan >& file. Sekarang, perhatikan bahwa ia mengatakan stderr dan stdout.

Dalam hal ini >file 2>&1kita melakukan pengalihan stdout (1) ke file, tetapi kemudian juga memberitahu stderr (2) untuk diarahkan ke tempat yang sama dengan stdout! Jadi tujuannya mungkin sama, tetapi idenya sedikit berbeda. Dengan kata lain "John, pergi ke sekolah; Suzzie pergi ke mana John pergi".

Bagaimana dengan preferensi? &>adalah suatu bashhal. Jadi, jika Anda mengirim skrip, itu tidak akan berhasil. Tetapi jika Anda 100% yakin skrip Anda hanya akan bekerja pada sistem dengan bash - maka tidak ada preferensi

Berikut adalah contoh dengan dash, Debian Amquist Shell yang merupakan default Ubuntu.

$ grep "YOLO" * &> /dev/null
$ grep: Desktop: Is a directory
grep: Documents: Is a directory
grep: Downloads: Is a directory
grep: Music: Is a directory
grep: Pictures: Is a directory
grep: Public: Is a directory
grep: Templates: Is a directory
grep: Videos: Is a directory
grep: YOLO: Is a directory
grep: bin: Is a directory

Seperti yang Anda lihat, stderr tidak sedang diarahkan

Untuk mengatasi suntingan Anda dalam pertanyaan, Anda dapat menggunakan pernyataan if untuk memeriksa variabel $ SHELL dan mengubah arahan yang sesuai

Tetapi untuk sebagian besar kasus > file 2>&1harus bekerja


Dalam istilah yang lebih teknis, formulir [integer]>&wordini disebut Duplicating Output File Descriptor , dan merupakan fitur yang ditentukan oleh standar Bahasa Perintah POSIX Shell, yang didukung oleh sebagian besar kerang yang sesuai dengan POSIX dan mirip-Brourne.

Lihat juga Apa maksud & tepatnya dalam redirection output?

Sergiy Kolodyazhnyy
sumber
Lalu apa yang terjadi ketika menggunakan pada beberapa cangkang lain?
Maythux
zsh mendukung &>.... @ Maythux Dalam kerang yang tidak mendukung &>misalnya dashAnda perlu menggunakan >file 2>&1pengalihan sepele ..
heemayl
Lalu yang mana yang digunakan jika saya ingin memastikan skrip saya akan kompatibel dengan shell yang berbeda
Maythux
3
@Maythux Gunakan >file 2>&1. Ini bekerja pada semua kerang
Sergiy Kolodyazhnyy
1
@ Kerang TSJNachos117 yang diatur /etc/passwduntuk setiap pengguna adalah kerang interaktif. Skrip sistem biasanya untuk dash kecuali ditentukan lain. Adapun apa yang default, itu ditentukan oleh apa yang disinkronkan ke /bin/shDalam kasus Ubuntu itu dash. Di RHEL itu adalah bash, di FreeBSD itu adalah tcsh sumber dan sumber lain
Sergiy Kolodyazhnyy
7

Saya biasanya akan merekomendasikan mengikuti cara Bourne-again SHell dalam melakukan sesuatu, karena bash bisa dibilang shell Unix paling populer di luar sana. Bash biasanya menggunakan salah satu &>atau 2>&1. IMHO, tidak ada yang "sempurna", jadi saya sarankan melupakan omong kosong itu. Secara realistis, yang mana yang harus Anda gunakan tergantung pada apa yang Anda coba lakukan.

2>&1menggabungkan stderr dengan stdout, yang dapat berguna jika, misalnya, Anda ingin mem-pipe teks stderr. Jadi, misalnya, jika Anda ingin melihat apakah suatu program mencetak pesan stderr tertentu, tetapi tidak ingin layar Anda diisi dengan (mungkin) sampah yang tidak penting, Anda dapat melakukan sesuatu seperti program 2>&1 | grep crashed, yang akan mencari stdout dan stderr dari suatu program disebut "program" untuk kata "crash".

Di sisi lain, jika Anda tidak ingin program untuk mencetak apa pun, Anda bisa menjalankannya program &> /dev/null, yang akan mengarahkan ulang stderr dan stdout ke / dev / null, file khusus yang secara ajaib membuat semuanya hilang. Atau, jika Anda ingin menyimpan output dari suatu program (mungkin untuk melaporkan bug atau sesuatu), Anda bisa mengarahkan ulang stderr dan stdout ke file: program &> log.txtakan mengarahkan semua data ke file yang disebut "log.txt". Jika Anda mau, Anda bisa mengarahkan stdout dan stderr melalui program 2> log.txt > log.txtatau program 2>&1 | cat > log.txt, keduanya akan memiliki efek yang sama seperti menggunakan &>. Jika Anda melakukan sesuatu seperti program 2>&1 > file, hanya stdout yang akan diarahkan, tetapi stderr masih dapat disalurkan ke program lain, seperti cat, yang dapat diarahkan seperti yang ditunjukkan di atas. Namun, mengetik&>lebih mudah daripada contoh-contoh di atas, karena itu melibatkan mengetik lebih sedikit karakter (dan itu agak lebih mudah bagi manusia untuk membaca). Perhatikan bahwa program 2> log.txt > log.txtmungkin lebih baik bekerja pada cangkang non-bash.

PS: jika Anda khawatir tentang orang yang menggunakan kerang lain, ada sesuatu yang dapat Anda tambahkan untuk menjadi baris pertama dari skrip Anda yang disebut "angka ajaib", atau "shebang". Ini pada dasarnya adalah cara untuk memastikan komputer lain (terutama yang menjalankan sistem operasi mirip Unix) tahu program mana yang digunakan untuk menjalankan skrip. Script yang berbeda menggunakan shebang yang berbeda. Shebang untuk skrip bash terlihat seperti ini:

#!/bin/bash

Jika Anda menggunakan di atas sebagai baris pertama skrip yang diberikan, bash umumnya akan digunakan untuk mengeksekusi skrip tersebut. Ini akan membuat jauh lebih sulit bagi seseorang untuk secara tidak sengaja mengeksekusi skrip dengan shell yang salah.

PS: Saya tidak akan berbohong: sampai sekarang, saya tidak tahu ada yang bisa menggunakan >&, tetapi sejauh menyangkut bash, sepertinya melakukan hal yang sama &>. Anda belajar sesuatu yang baru setiap hari.

TSJNachos117
sumber
Meskipun saya setuju dengan Anda tentang penggunaan #!jalur untuk meminta secara eksplisit bash, itu tidak selalu tersedia di sistem lain. Sangat sering pengembang / sysadmin harus menulis skrip portabel untuk sistem yang bashmungkin tidak tersedia dan mungkin tidak berada di bawah kendali mereka untuk menginstal bash. Ini >file 2>&1hanya banyak portabel.
Sergiy Kolodyazhnyy
Anda membuat kesalahan pembalikan di atas, yang tidak menghasilkan hasil yang Anda klaim atau inginkan. Redirect stderr ke stdout, lalu redirect stdout meninggalkan stderr pada stdout asli.
ubfan1
Serg: Saya tidak bermaksud mengatakan bahwa bash itu universal. Namun, saya pikir lebih banyak orang yang menggunakannya daripada mengatakan (t) csh. Jika Anda tidak tahu apa yang orang lain gunakan, dan harus menebak, bash mungkin adalah taruhan terbaik Anda. Juga, saya biasanya tidak tahu tentang portabilitas, karena saya hanya menggunakan bash. Fakta yang >file 2>&1lebih portabel bagus untuk diketahui. Saya akan mengedit agar mencerminkan hal itu.
TSJNachos117
Ubfan1, terima kasih atas informasinya. Saya tidak akan pernah menduga dalam sejuta tahun bahwa bash tidak akan mengarahkan stderr ke file dalam kasus itu. Saya baru saja mengedit jawaban saya untuk mencegah orang lain melakukan kesalahan yang sama.
TSJNachos117
4

Dari Bash Reference Manual -> 3.6.4 Mengarahkan Output Standar dan Kesalahan Standar :

Konstruk ini memungkinkan output standar (deskriptor file 1) dan output kesalahan standar (deskriptor file 2) untuk diarahkan ke file yang namanya adalah perluasan kata.

Ada dua format untuk mengarahkan output standar dan kesalahan standar:

&>word

dan

>&word

Dari dua bentuk, yang pertama lebih disukai. Ini setara dengan semantik

>word 2>&1

Saat menggunakan formulir kedua, kata mungkin tidak diperluas ke angka atau '-'. Jika ya, operator redirection lainnya berlaku (lihat Duplicating File Descriptors di bawah) untuk alasan kompatibilitas.

Juga bagus untuk merujuk ke wiki Greg pada Input dan Output -> 4.2. Manipulasi Penjelasan File :

Untuk kenyamanan, Bash juga menyediakan bentuk pengalihan lain untuk Anda. Operator &> redirection sebenarnya hanya versi lebih pendek dari apa yang kami lakukan di sini [ 2>&1]; mengarahkan stdout dan stderr ke file.

fedorqui
sumber
4

Jadi Mengapa saya harus menggunakan &> dan bukan 2> & 1

2>&1 adalah shell Bourne / POSIX standar.

&>adalah ekstensi bash dan bukan standar de jure .

Jika Anda menulis skrip menggunakan ekstensi bash, cepat atau lambat Anda akan menemui kegagalan goresan kepala dengan pesan kesalahan sintaksis kriptik karena sedang dijalankan dalam shell standar.

Stephen M. Webb
sumber