Come posso comprimere un file su Linux sul posto, senza usare spazio su disco aggiuntivo?


20

Ho un disco da 100 GB con un file da 95 GB. Devo liberare un po 'di spazio sull'unità (e al momento il trasferimento del file dall'unità non è un'opzione). Il file si comprimerebbe bene con gzipo bz2qualsiasi altra cosa, ma tutti questi programmi scrivono il file compresso in un file separato. Non ho abbastanza spazio libero per questo.

Esiste un modo per utilizzare gli strumenti di compressione standard o altre utilità Unix per comprimere il file senza utilizzare spazio su disco aggiuntivo (o almeno una quantità minima di spazio su disco aggiuntivo)? Sto immaginando qualcosa che comprime parte del file alla volta e scrive i risultati direttamente sul file. Mi rendo conto che questo sarebbe rischioso, poiché il file sarebbe danneggiato se la compressione fosse interrotta, ma non credo di avere scelta.


Un'ultima opzione che usavamo nel mio vecchio posto era quella di avere una directory da qualche parte che contenesse un sacco di file 1G pieni di immondizia. Quindi, se hai avuto un pizzico, potresti rimuoverne alcuni per darti un po 'di spazio di emergenza.

Risposte:


13

Questa è una prova del concetto bash one-liner, ma dovrebbe iniziare. Utilizzare a proprio rischio.

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

Funziona reindirizzando i dati gz a un processo dd che li riscrive nello stesso file. Al termine, il file viene troncato alla dimensione dell'output gz.

Questo presuppone che l'ultima riga dell'output di dd corrisponda:

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

Dove il primo campo è un numero intero di byte scritti. Questa è la dimensione in cui il file dovrà essere troncato. Non sono sicuro al 100% che il formato di output sia sempre lo stesso.


Trucco astuto. Potresti spiegare perché conv=notruncè necessario?
sleske,

Forse no. gzip -c file | dd of=filesembra funzionare altrettanto bene.
user710307,

1
Le persone alla domanda collegata l'hanno provato (e l'ho provato anche io); non funziona in generale. Sembra funzionare solo per file molto piccoli, forse perché gzip leggerà un piccolo file nella RAM prima di comprimerlo. Per file di grandi dimensioni (pochi MB), non funziona, anche se sono comprimibili.
sleske,

3
Sì. Quindi conv = notrunc è necessario.
user710307,

1
Non è possibile che in qualsiasi momento il programma di compressione (ad es. gzip) Scriva più byte di intestazione e dati rispetto ai byte di dati originali, sovrascrivendo così alcune parti del file? Immagino che questo dipenda dal programma di compressione scelto. Qualcuno ha idea di come evitare che ciò accada o quanto (im) probabile sia?
Daniel Böhmer,

7

Non è così tanto gzipe bzip2sovrascrive l'originale. Piuttosto, scrivono i dati compressi sul disco come nuovo file e, se l'operazione ha esito positivo, scollegano il file non compresso originale.

Se si dispone di RAM sufficiente, è possibile scrivere uno script per comprimere temporaneamente i file in un tmpfsfilesystem, quindi rimuovere l'originale sul disco e sostituirlo con la versione compressa. Forse qualcosa del genere:

# 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

Basta essere consapevoli dell'utilizzo della memoria, poiché tmpfsè essenzialmente un disco RAM. Un file di output di grandi dimensioni potrebbe facilmente far morire di fame il sistema e causare altri problemi.


1
È abbastanza folle da funzionare
Andrew Lambert,

Mi piace spingere la busta.
James Sneeringer,

3

Non esiste uno strumento che funzioni in questo modo, proprio per il motivo che dai. Poche persone sono disposte a scrivere uno strumento che implementa deliberatamente comportamenti rischiosi.


Speravo che sarebbe stata un'opzione non sicura e non predefinita per un'utilità. Potresti pensare ad un'alternativa? Esiste un modo per troncare un file in atto, ad esempio rimuovere i primi 2 GB? Ciò mi consentirebbe di utilizzare il mio spazio libero limitato per comprimere un blocco alla volta, riducendo il file di origine mentre procedevo.
Lee

Non c'è davvero alcun modo sano di rimuovere i dati dall'inizio di un file su qualsiasi filesystem, con qualsiasi strumento.
Ignacio Vazquez-Abrams,

2
Ma puoi rimuovere i dati dalla fine del file. Si può fare in linea di principio. Taglia i dati dalla fine del file per metterli in file separati, troncando i file originali mentre procedi. Quindi comprimi i file in ordine avanti, eliminandoli mentre procedi. Sarebbe una seccatura da attuare e se qualcosa andasse storto saresti fregato. Ma è possibile
David Schwartz,

1

I comandi split e csplit potrebbero essere usati per dividere il file di grandi dimensioni in parti più piccole e quindi comprimerli individualmente. Il riassemblaggio richiederebbe piuttosto tempo.


Un'altra buona opzione. Uno potrebbe probabilmente scrivere alcuni script per fare questo. Tuttavia, questo produce molti file compressi separatamente, che dovranno essere concatenati dopo la decompressione, il che non è così piacevole.
sleske,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.