Bagaimana saya bisa mengompres file di Linux di tempat, tanpa menggunakan ruang disk tambahan?

20

Saya mendapatkan drive 100GB yang memiliki file 95GB. Saya perlu mengosongkan ruang di drive (dan sekarang mentransfer file dari drive bukan pilihan). File akan dikompres dengan baik dengan gzipatau bz2atau apa pun, tetapi semua program ini menulis file terkompresi ke file terpisah. Saya tidak punya cukup ruang kosong untuk ini.

Apakah ada cara menggunakan alat kompresi standar atau utilitas Unix lainnya untuk mengompres file tanpa menggunakan ruang disk tambahan (atau setidaknya ruang disk tambahan minimal)? Saya membayangkan sesuatu yang mengkompres bagian file sekaligus dan menulis hasilnya langsung di atas file. Saya menyadari ini akan berisiko, karena file akan rusak jika kompresi terputus, tetapi saya rasa saya tidak punya pilihan.

Lee
sumber
Satu opsi terakhir yang biasa kami gunakan di tempat lama saya adalah memiliki dir di suatu tempat yang berisi sejumlah file 1G penuh dengan sampah. Kemudian, jika Anda mengalami kesulitan, Anda dapat menghapus beberapa dari mereka untuk memberi Anda sedikit ruang darurat.

Jawaban:

13

Ini adalah bukti dari konsep bash one-liner, tetapi harus membantu Anda memulainya. Gunakan dengan risiko Anda sendiri.

truncate -s `gzip -c file | dd of=file conv=notrunc 2>&1 | sed -n '$ s/ .*$// p'` file
mv file file.gz

Ini bekerja dengan memipakan data gz ke proses dd yang menulisnya kembali ke file yang sama. Setelah selesai, file dipotong ke ukuran output gz.

Ini mengasumsikan bahwa baris terakhir dari output dd cocok:

4307 bytes (4,3 kB) disalin, 2,5855e-05 s, 167 MB / s

Di mana bidang pertama adalah integer byte yang ditulis. Ini adalah ukuran file yang harus dipotong. Saya tidak 100% yakin bahwa format output selalu sama.

pengguna710307
sumber
Trik bagus. Bisakah Anda menjelaskan mengapa conv=notruncitu perlu?
sleske
Mungkin tidak. gzip -c file | dd of=filetampaknya bekerja juga.
user710307
1
Orang-orang di pertanyaan terkait mencobanya (dan saya juga mencobanya); itu tidak bekerja secara umum. Tampaknya ini hanya berfungsi untuk file yang sangat kecil - mungkin karena gzip akan membaca file kecil ke dalam RAM sebelum mengompresnya. Untuk file besar (beberapa MB), itu tidak berfungsi, bahkan jika mereka kompresibel.
sleske
3
Ya. Jadi conv = notrunc diperlukan.
user710307
1
Apakah tidak mungkin setiap saat program kompresi (misalnya gzip) menulis lebih banyak header dan byte data daripada byte data asli, sehingga menimpa beberapa bagian file? Saya kira ini tergantung pada program kompresi yang dipilih. Adakah yang tahu bagaimana mencegah hal ini terjadi atau bagaimana kemungkinannya?
Daniel Böhmer
7

Ini tidak begitu banyak gzipdan bzip2menimpa yang asli. Sebaliknya, mereka menulis data terkompresi ke disk sebagai file baru, dan jika operasi itu berhasil, mereka memutuskan tautan file asli yang tidak terkompresi.

Jika Anda memiliki RAM yang cukup, Anda dapat menulis skrip untuk mengompresi sementara file dalam tmpfssistem file, kemudian menghapus yang asli pada disk dan menggantinya dengan versi terkompresi. Mungkin kira-kira seperti ini:

# some distributions mount /dev/shm as tmpfs; replace with bzip2 if you prefer
if gzip -q9c /full/disk/somefile > /dev/shm/somefile.gz
then
    rm -f /full/disk/somefile && mv -i /dev/shm/somefile.gz /full/disk
fi

Berhati-hatilah dengan penggunaan memori Anda, karena tmpfspada dasarnya ini adalah disk RAM. File keluaran besar dapat dengan mudah membuat sistem kelaparan dan menyebabkan masalah lain bagi Anda.

James Sneeringer
sumber
1
Itu cukup gila untuk berhasil
Andrew Lambert
Saya suka mendorong amplop.
James Sneeringer
3

Tidak ada alat yang bekerja dengan cara ini, untuk alasan yang Anda berikan. Hanya sedikit orang yang mau menulis alat yang dengan sengaja menerapkan perilaku berisiko.

Ignacio Vazquez-Abrams
sumber
Saya berharap itu akan menjadi opsi yang tidak aman dan tidak standar untuk suatu utilitas. Bisakah Anda memikirkan alternatif? Apakah ada cara untuk memotong file di tempat, misalnya menghapus 2 GB pertama? Itu akan memungkinkan saya menggunakan ruang kosong saya yang terbatas untuk memampatkan satu bongkahan sekaligus, mengecilkan file sumber ketika saya pergi.
Lee
Benar-benar tidak ada cara yang waras untuk menghapus data dari awal file di sistem file apa pun, dengan alat apa pun.
Ignacio Vazquez-Abrams
2
Tetapi Anda dapat menghapus data dari akhir file. Itu bisa dilakukan secara prinsip. Anda mengiris data dari ujung file untuk dimasukkan ke file yang terpisah, memotong file asli saat Anda pergi. Kemudian Anda mengompres file dalam urutan ke depan, menghapusnya saat Anda pergi. Akan sulit untuk diterapkan dan jika ada kesalahan Anda akan kacau. Tapi itu mungkin.
David Schwartz
1

Perintah split dan csplit dapat digunakan untuk membagi file besar menjadi bagian-bagian yang lebih kecil, dan kemudian kompres secara individual. Merangkai kembali akan memakan waktu.

Brian
sumber
Pilihan lain yang bagus. Seseorang mungkin dapat menulis beberapa skrip untuk melakukan ini. Namun, ini menghasilkan banyak file yang dikompresi secara terpisah, yang perlu disatukan kembali setelah uncompressing, yang tidak begitu baik.
sleske