追加のディスク容量を使用せずに、Linuxでファイルをインプレースで圧縮するにはどうすればよいですか?


20

95GBファイルのある100GBドライブを持っています。ドライブの空き容量を増やす必要があります(現在、ドライブからファイルを転送することはできません)。ファイルには、とよく圧縮でしょうgzipbz2または何が、すべてのこれらのプログラムは、別のファイルに圧縮されたファイルを書き込みます。このための十分な空き領域がありません。

標準の圧縮ツールまたは他のUnixユーティリティを使用して、追加のディスクスペース(または少なくとも最小限の追加ディスクスペース)を使用せずにファイルを圧縮する方法はありますか?私は、一度にファイルの一部を圧縮し、その結果を直接ファイルに書き込むものを描いています。圧縮が中断されるとファイルが破損するため、これは危険であると認識していますが、選択の余地はないと思います。


私が古い場所で使用していた最後のオプションの1つは、ゴミでいっぱいの1Gファイルの束を含むディレクトリをどこかに置くことでした。その後、ピンチに陥った場合は、それらの一部を削除して、少しの緊急スペースを確保できます。

回答:


13

これは概念実証のbashワンライナーですが、開始する必要があります。自己責任。

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

これは、gzデータを同じプロセスに書き戻すddプロセスにパイプすることで機能します。完了すると、ファイルはgz出力のサイズに切り捨てられます。

これは、ddの出力の最後の行が一致すると仮定しています。

4307バイト(4.3 kB)コピー、2.5855e-05秒、167 MB /秒

最初のフィールドは書き込まれたバイトの整数です。これは、ファイルを切り捨てる必要があるサイズです。出力形式が常に同じであることを100%確信しているわけではありません。


気の利いたトリック。なぜconv=notrunc必要なのか説明してもらえますか?
-sleske

たぶんそうではありません。gzip -c file | dd of=file同様に機能するようです。
-user710307

1
リンクされた質問の人々はそれを試しました(そして私も試しました)。一般的には機能しません。非常に小さなファイルに対してのみ機能するようです-おそらくgzipは圧縮する前に小さなファイルをRAMに読み込むからです。大きなファイル(数MB)の場合、たとえ圧縮可能であっても機能しません。
-sleske

3
うん。したがって、conv = notruncが必要です。
user710307

1
圧縮プログラム(たとえばgzip)がいつでも元のデータバイトよりも多くのヘッダーとデータバイトを書き込み、ファイルの一部を上書きすることはできませんか?これは、選択した圧縮プログラムに依存すると思います。誰もこれを防ぐ方法や、それがどのように(可能性が高い)考えを持っていますか?
ダニエルベーマー

7

それはそれほどではなく、オリジナルgzipbzip2上書きします。むしろ、圧縮データを新しいファイルとしてディスクに書き込み、その操作が成功すると、元の非圧縮ファイルのリンクを解除します。

十分なRAMがある場合は、tmpfsファイルシステム内のファイルを一時的に圧縮するスクリプトを作成し、ディスク上の元のファイルを削除して、圧縮バージョンに置き換えることができます。たぶんこのようなもの:

# 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

tmpfs基本的にRAMディスクであるため、メモリ使用量に注意してください。大きな出力ファイルはシステムを簡単に枯渇させ、他の問題を引き起こす可能性があります。


1
それは動作するのに十分クレイジーです
アンドリューランバート

封筒を押すのが好きです。
ジェームズ・スニーリンガー

3

あなたが与えた正確な理由から、このように機能するツールはありません。危険な行動を意図的に実装するツールを作成する人はほとんどいません。


私はそれがユーティリティにとって安全ではない、デフォルト以外のオプションになることを望んでいました。別の方法を考えてもらえますか?ファイルを切り捨てて、たとえば最初の2 GBを削除する方法はありますか?これにより、制限された空き領域を使用して、一度に1つのチャンクを圧縮し、ソースファイルを縮小していきます。
リー

どんなツールでも、ファイルシステムのファイルの先頭からデータを削除する正しい方法はありません。
イグナシオバスケス-エイブラムス

2
ただし、ファイルの末尾からデータを削除できます。原理的にはできます。ファイルの終わりからデータをスライスして個別のファイルに入れ、元のファイルを切り捨てます。次に、ファイルを順方向に圧縮し、使用中に削除します。実装するのは苦痛であり、何か問題が発生した場合は、めちゃくちゃになります。しかし、それは可能です。
デビッドシュワルツ

1

splitおよびcsplitコマンドを使用して、大きなファイルを小さな部分に分割し、それらを個別に圧縮できます。ただし、再組み立てには時間がかかります。


別の良いオプション。おそらくこれを行うためのスクリプトを作成できます。ただし、これにより、多数の個別に圧縮されたファイルが生成されます。これらのファイルは、圧縮解除後に再連結する必要がありますが、あまり良くありません。
-sleske
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.