Apakah mengurutkan dukungan menyortir file di tempat, seperti `sed --in-place`?

80

Apakah saya buta atau ada ada pilihan seperti --in-placeuntuk sort?

Untuk menyimpan hasil ke file input, sed menggunakan -i( --in-place).

Mengarahkan output sortke file input

sort < f > f

hasil membuatnya kosong. Jika tidak ada --in-placepilihan - mungkin ada beberapa trik bagaimana melakukan ini dengan cara yang praktis ?

(Satu-satunya hal yang muncul di benak saya:

sort < f > /tmp/f$$ ; cat /tmp/f$$ > f ; rm /tmp/f$$

Pindah bukanlah pilihan yang tepat, karena izin file mungkin berubah. Itu sebabnya saya menimpa dengan isi file temp yang kemudian saya hapus.)

Grzegorz Wierzowiecki
sumber
Ada juga insitu, yang memungkinkan perintah apa pun untuk digunakan di tempat.
sr_
@ sr_, itu perintah yang menarik, tetapi tidak bekerja dengan perintah apa pun , hanya yang menulis tidak lebih cepat dari yang mereka baca (jika tidak, akan merusak file input sebelum perintah membacanya). Tidak ada jaminan bahwa itu akan berhasil sort.
cjm
@ cjm, saya benar-benar tidak yakin, tetapi bukankah ini seharusnya menangani kasus itu?
sr_
@ sr_, saya pikir Anda benar. Saya membaca deskripsi alih-alih melihat sumbernya. Meskipun untuk file yang sangat besar, mungkin kehabisan memori untuk buffer dan crash (sepertinya tidak memeriksa pengembalian NULL dari malloc).
cjm
@ cjm: Oh ya, tentu saja.
sr_

Jawaban:

110

sortmemiliki -o, --outputopsi yang menggunakan nama file sebagai argumen. Jika sama dengan file input, ia menulis hasilnya ke file sementara, kemudian menimpa file input asli (persis sama dengan apa yang sed -idilakukan).

Dari GNU sorthalaman info:

`-o OUTPUT-FILE'
`--output=OUTPUT-FILE'
      Write output to OUTPUT-FILE instead of standard output.  Normally,
      `sort' reads all input before opening OUTPUT-FILE, so you can
      safely sort a file in place by using commands like `sort -o F F'
      and `cat F | sort -o F'.  However, `sort' with `--merge' (`-m')
      can open the output file before reading all input, so a command
      like `cat F | sort -m -o F - G' is not safe as `sort' might start
      writing `F' before `cat' is done reading it.

      On newer systems, `-o' cannot appear after an input file if
      `POSIXLY_CORRECT' is set, e.g., `sort F -o F'.  Portable scripts
      should specify `-o OUTPUT-FILE' before any input files.

dan dari Spesifikasi Basis Grup Terbuka, Edisi 7 :

-o  output
    Specify the name of an output file to be used instead of the standard 
    output. This file can be the same as one of the input files.
enzotib
sumber
Tepat! Berhasil ! Saya tidak dapat melihat petunjuk tentang hal ini man sort- apakah ini fitur tidak berdokumen? Apakah ini standar dan portabel?
Grzegorz Wierzowiecki
@GrzegorzWierzowiecki: lihat pembaruan.
enzotib
Jawaban bagus :).
Grzegorz Wierzowiecki
1
Singkatnya: sort -o <filename> <filename>akan dengan aman menyortir file di tempat.
phyatt
11

Anda dapat menggunakan spongefungsi, yang pertama membasahi stdindan kemudian menulisnya ke file, seperti:

sort < f | sponge f

Kelemahan dari spongeini adalah ia akan menyimpan output sementara dalam memori, yang dapat bermasalah untuk file besar. Kalau tidak, Anda harus menulisnya ke file terlebih dahulu dan kemudian menimpa file asli.

Namun seperti yang ditunjukkan oleh jawaban lain, modifikasi di tempat pada umumnya bukan ide yang baik, karena di tengah-tengah proses (misalnya yang sponge), mesin mungkin macet dan kemudian Anda dapat kehilangan file asli dan baru. Anda lebih baik menulisnya ke file yang berbeda dan kemudian menggunakan mvinstruksi atom (bergerak).

Willem Van Onsem
sumber
7

Berbahaya jika menimpa file input dengan file output, karena jika program atau sistem crash saat file sedang ditulis, Anda telah kehilangan keduanya.

Beberapa program (kebanyakan versi GNU) memiliki opsi in-place (misalnya -ipada perl dan GNU sed; -opada GNU sort). Mereka bekerja dengan meletakkan data dalam file sementara dan kemudian memindahkannya ke tempatnya. Untuk program yang tidak memiliki opsi tersebut, Colin Watson spongeutilitas (termasuk dalam MoreUtils Joey Hess ) melakukan pekerjaan dengan aman untuk setiap program (contoh: Dapatkah saya membuat cut? Mengubah file di tempat ; Bagaimana saya bisa membuat iconv mengganti file input dengan dikonversi output? ).

Hanya dalam kasus-kasus langka di mana Anda tidak dapat membuat kembali file asli dengan izin yang sama saya sarankan menimpa file di tempat. Dalam hal ini, Anda sebaiknya menyimpan input asli di suatu tempat. Dan kemudian Anda cukup memproses salinan input dan mengirimkannya ke file asli.

cp -p f ~/f.backup
sort <~/f.backup >|f
rm ~/f.backup # optional
Gilles
sumber
1
sort -obukan spesifik GNU, dan dirancang khusus untuk mengunggah file yang ada. sorttidak dapat mulai menulis outputnya sebelum membaca inputnya sepenuhnya (menggunakan memori atau file sementara untuk menyimpan data), jadi itu datang secara alami bahwa itu harus dapat menimpa inputnya.
Stéphane Chazelas
Dan sebenarnya, ini adalah satu kasus di mana GNU sorttidak POSIX karena sort -mo file1 file1 file2tidak dijamin untuk bekerja sementara orang tradisional sorttahu bagaimana mengatasinya (dibaca di Unix V7 pada tahun 70-an).
Stéphane Chazelas
@ JoelCross Aneh, sort -obekerja untuk saya dengan coreutils 8.25 dan properti didokumentasikan dalam manual (mencatat bahwa itu hanya kasus ketika menyortir, bukan saat penggabungan). Jika Anda dapat mereproduksi ini, kirim laporan bug (menunjukkan baris perintah yang tepat, file input yang tepat, sistem tempat Anda menjalankannya, dan bagaimana Anda mendapatkan binernya).
Gilles
4

Gunakan -oatau coba vim-way:

$ ex -s +'%!sort' -cxa file.txt
kenorb
sumber