Mengapa `sort <" $ f1 "` lebih disukai daripada `sort -" $ f1 "`, dan mengapa ini lebih disukai daripada `sort" $ f1 "`?

29

Dari /unix//a/458074/674

Ingatlah untuk menggunakan -- saat memberikan argumen arbitrer ke perintah (atau gunakan pengalihan jika memungkinkan). Jadi sort -- "$f1"atau lebih baik sort < "$f1"daripada sort "$f1".

Mengapa lebih disukai untuk digunakan --dan pengalihan?

Mengapa sort < "$f1"lebih disukai daripada sort -- "$f1"?

Mengapa sort -- "$f1"lebih disukai daripada sort "$f1"?

Terima kasih.

Tim
sumber

Jawaban:

55
sort "$f1"

gagal untuk nilai $f1yang dimulai dengan -atau di sini untuk kasus sortbeberapa yang dimulai dengan +(dapat memiliki konsekuensi parah untuk file yang dipanggil -o/etc/passwdmisalnya).

sort -- "$f1"

(di mana -- menandakan akhir opsi) menangani sebagian besar masalah tersebut tetapi masih gagal untuk file yang dipanggil -(yang sortmenafsirkan sebagai stdin sebagai gantinya).

sort < "$f1"

Tidak memiliki masalah itu.

Di sini, itu shell yang membuka file. Ini juga berarti bahwa jika file tidak dapat dibuka, Anda juga akan mendapatkan pesan kesalahan yang berpotensi lebih berguna (misalnya, kebanyakan shell akan menunjukkan nomor baris dalam skrip), dan pesan kesalahan akan konsisten jika Anda menggunakan pengalihan sedapat mungkin untuk membuka file.

Dan masuk

sort < "$f1" > out

(bertentangan dengan sort -- "$f1" > out), jika "$f1"tidak dapat dibuka, outtidak akan dibuat / terpotong dan sortbahkan tidak dijalankan.

Untuk menghapus beberapa kebingungan yang mungkin terjadi (mengikuti komentar di bawah), itu tidak mencegah perintah mmap()untuk memasukkan file atau lseek()memasukkannya ke dalam file (tidak sortjuga melakukannya) asalkan file itu sendiri dapat dicari. Satu-satunya perbedaan adalah bahwa file dibuka sebelumnya dan pada deskriptor file 0 oleh shell sebagai lawan kemudian oleh perintah mungkin pada deskriptor file yang berbeda. Perintah masih dapat mencari / mmap fd 0 sesuka hati. Itu tidak menjadi bingung dengan di cat file | cmdmana cmdstdin kali ini adalah pipa yang tidak dapat dicari / dicari.

Stéphane Chazelas
sumber
4
Hanya ingat bahwa menggunakan kekuatan pengalihan sortuntuk membaca data secara berurutan dan Anda tidak dapat mmapfile. Meskipun sortmungkin tidak memiliki banyak masalah dengan itu, pertimbangkan kinerja less <filedan less file. Dalam kasus pertama lessharus menyimpan seluruh isi file dalam memori, dalam kasus kedua itu diperbolehkan untuk membaca hanya bagian-bagian yang diinginkannya. Sekarang bayangkan itu fileadalah file log 100GB ...
styrofoam fly
7
@styrofoamfly: Benar less <filemenyimpan semua file dalam memori, tetapi tidak dipaksa, ini adalah kekurangan dari kurang. Hanya cat file | lessterpaksa. Lihat less /dev/fd/0 <f, yang tidak menyimpan file dalam memori, meskipun ia menerimanya di stdin. Ini adalah kesalahpahaman umum bahwa stdin di Unix tidak dapat dilihat. Faktanya, itu bisa dicari, tergantung pada jenis file.
Poin
@styrofoamfly Maksud Anda read()membaca data secara berurutan dari suatu file, sementara mmap()membaca seluruh file ke dalam memori sekaligus?
Tim
1
@JohnBollinger No. Tanggal kembali ke setidaknya sejauh getopt dari SysIII pada tahun 1980 sebelum proyek GNU dimulai dan wajib didukung untuk sebagian besar utilitas standar termasuk sortoleh POSIX. Tetapi memang benar bahwa itu tidak selalu didukung.
Stéphane Chazelas
2
Permintaan maaf saya, @ StéphaneChazelas, Anda benar tentang asal-usul konvensi, dan saya selanjutnya akan menetapkan bahwa spesifikasi POSIX untuk getopt()fungsi C mengakui pentingnya argumen ini --. Tetapi poin utama adalah yang Anda terima: penanganan argumen adalah domain dari masing-masing program, dan tidak semua memperlakukan --secara khusus.
John Bollinger
17

Masalahnya adalah nama file yang dimulai dengan tanda hubung. sort "$f1"tidak berfungsi jika nilai f1dimulai dengan -karena perintah akan menafsirkan nilai sebagai opsi. Ini biasanya menghasilkan kesalahan tetapi bahkan bisa menyebabkan lubang keamanan . Dengan sort -- "$f1", argumen dasbor ganda --berarti "tidak ada opsi di luar titik ini" sehingga nilai f1tidak akan ditafsirkan sebagai opsi. Tetapi masih ada satu kasus tepi: jika nilai f1adalah tanda hubung dan tidak ada yang lain, maka itu bukan pilihan, itu argumen -, yang berarti "input standar" (karena argumennya adalah file input; untuk file output itu berarti "output standar").

Menggunakan pengalihan menghindari semua jebakan ini.

Ini berlaku untuk sebagian besar perintah, bukan hanya sort.

Gilles 'SANGAT berhenti menjadi jahat'
sumber
Apakah Anda mengatakan itu sort < "$f1"akan berhasil jika nilainya sama dengan -? Itu tidak dalam shell saya sudah mencoba.
grawity
@ kegembiraan, bandingkan seq 10 > -; sort -dengan seq 10 > -; sort < -.
Stéphane Chazelas