web-dev-qa-db-ja.com

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

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

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

21
Lee

これは、概念実証の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%わかりません。

14
user710307

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

十分なRAMがある場合は、a 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ディスクであるので、メモリの使用量に注意してください。大きな出力ファイルはシステムを簡単に枯渇させ、他の問題を引き起こす可能性があります。

8

正確に言うと、このように機能するツールはありません。危険な行動を意図的に実装するツールを喜んで書く人はほとんどいません。

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

1
Brian