Ek disk alanı kullanmadan bir dosyayı yerinde Linux'ta nasıl sıkıştırabilirim?


20

95GB'lık bir dosyaya sahip 100GB'lık bir sürücüm var. Sürücüde biraz yer açmam gerekiyor (ve şu anda dosyayı sürücüden aktarmak bir seçenek değil). Dosya gzipya bz2da ya da her neyse iyi sıkıştırır , ancak tüm bu programlar sıkıştırılmış dosyayı ayrı bir dosyaya yazar. Bunun için yeterli boş alanım yok.

Ek disk alanı (veya en azından minimum miktarda ek disk alanı) kullanmadan dosyayı sıkıştırmak için standart sıkıştırma araçlarını veya diğer Unix yardımcı programlarını kullanmanın bir yolu var mı? Dosyanın bir kısmını bir seferde sıkıştıran ve sonuçları doğrudan dosyanın üzerine yazan bir şey hayal ediyorum. Sıkıştırma kesilirse dosya bozulacağı için bunun riskli olacağını fark ettim, ancak bir seçeneğim olduğunu düşünmüyorum.


Eski yerimde kullandığımız son bir seçenek, çöple dolu 1G dosyalarının bir demetini içeren bir yere sahip olmaktı. Sonra, bir tutam içine girdiyseniz, size biraz acil durum alanı vermek için bazılarını çıkarabilirsiniz.

Yanıtlar:


13

Bu, tek katmanlı bir kavramın kanıtıdır, ancak başlamanız gerekir. Kendi sorumluluğunuzdadır kullanın.

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

Bu, gz verilerini aynı dosyaya yazan bir dd işlemine bağlayarak çalışır. Tamamlandığında, dosya gz çıktısının boyutuna kesilir.

Bu, dd'nin çıkışının son satırının eşleştiğini varsayar:

4307 bayt (4.3 kB) kopyalandı, 2.5855e-05 s, 167 MB / s

İlk alan, yazılan bayt tamsayısıdır. Bu, dosyanın kesilmesi gereken boyuttur. Çıktı biçiminin her zaman aynı olduğundan% 100 emin değilim.


Şık numara. Neden conv=notruncgerekli olduğunu açıklayabilir misiniz ?
sleske

Belki de değildir. gzip -c file | dd of=fileaynı şekilde çalışıyor gibi görünüyor.
user710307

1
Bağlantılı sorudaki insanlar denedi (ve ben de denedim); genel olarak çalışmaz. Sadece çok küçük dosyalar için çalışıyor gibi görünüyor - belki gzip sıkıştırmadan önce RAM'a küçük bir dosya okuyacaktır. Büyük dosyalar için (birkaç MB), sıkıştırılabilir olsalar bile çalışmaz.
sleske

3
Evet. Yani conv = notrunc gereklidir.
user710307

1
Sıkıştırma programının (örn. gzip) Herhangi bir zamanda orijinal veri baytlarından daha fazla başlık ve veri baytı yazması ve böylece dosyanın bazı bölümlerinin üzerine yazılması mümkün değil mi? Bu seçilen sıkıştırma programına bağlıdır sanırım. Herkes bunun nasıl önleneceği veya nasıl (im) olası bir fikir var mı?
Daniel Böhmer

7

O kadar değil gzipve bzip2orijinalin üzerine yazılıyor. Bunun yerine, sıkıştırılmış verileri diske yeni bir dosya olarak yazarlar ve bu işlem başarılı olursa, orijinal sıkıştırılmamış dosyanın bağlantısını kaldırırlar.

Yeterli RAM'iniz varsa, dosyaları bir tmpfsdosya sistemindeki geçici olarak sıkıştırmak için bir komut dosyası yazabilir , ardından orijinali diskten çıkarabilir ve sıkıştırılmış sürümle değiştirebilirsiniz. Belki böyle bir şey:

# 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

tmpfsAslında bir RAM disk olduğundan , bellek kullanımınıza dikkat edin . Büyük bir çıktı dosyası sistemi kolayca aç bırakabilir ve sizin için başka sorunlara neden olabilir.


1
Bu işe yarayacak kadar çılgın
Andrew Lambert

Zarfı itmeyi seviyorum.
James Sneeringer

3

Tam olarak verdiğiniz sebep için bu şekilde çalışan bir araç yoktur. Çok az insan kasıtlı olarak riskli davranışı uygulayan bir araç yazmaya isteklidir.


Bir yardımcı program için güvenli olmayan, varsayılan olmayan bir seçenek olacağını umuyordum. Bir alternatif düşünebilir misiniz? Örneğin, ilk 2 GB'yi kaldırmak için bir dosyayı kısaltmanın bir yolu var mı? Bu, sınırlı boş alanımı her seferinde bir yığın sıkıştırmak için kullanmamı sağladı, gittiğimde kaynak dosyayı daralttı.
Lee

Herhangi bir araçla herhangi bir dosya sistemindeki bir dosyanın başlangıcından veri kaldırmanın gerçekten mantıklı bir yolu yoktur.
Ignacio Vazquez-Abrams

2
Ancak verileri dosyanın sonundan kaldırabilirsiniz . Prensip olarak yapılabilir. Ayrı dosyaları koymak için dosyanın sonundaki verileri dilimlersiniz, orijinal dosyaları giderken kesersiniz. Daha sonra dosyaları ileriye doğru sıkıştırırsınız ve giderken silersiniz. Uygulamak acı verici olur ve bir şeyler ters giderse berbat olursunuz. Ama bu mümkün.
David Schwartz

1

Böl ve csplit komutları, büyük dosyayı daha küçük parçalara bölmek ve sonra bunları tek tek sıkıştırmak için kullanılabilir. Yeniden montaj oldukça zaman alıcı olacaktır.


Başka bir iyi seçenek. Muhtemelen bunu yapmak için bazı senaryolar yazabilirsiniz. Bununla birlikte, bu, sıkıştırılmadan sonra yeniden birleştirilmesi gereken birçok ayrı sıkıştırılmış dosya verir, bu da hoş değildir.
sleske
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.