Come concatenare due file di grandi dimensioni con pochissimo spazio libero su disco? [chiuso]

StackOverflow https://stackoverflow.com/questions/290700

Domanda

Supponi di avere due file di grandi dimensioni (diversi GB) che desideri concatenare insieme, ma che hai pochissimo spazio libero su disco (diciamo circa duecento MB). Cioè, dati file1 e file2 , vuoi finire con un singolo file che è il risultato della concatenazione di file1 e file2 insieme byte per byte ed elimina i file originali.

Non puoi fare l'ovvio cat file2 > > file1; rm file2 , poiché tra le due operazioni si esaurirebbe lo spazio su disco.

Le soluzioni su tutte le piattaforme con strumenti gratuiti o non gratuiti sono benvenute; questo è un problema ipotetico che ho pensato mentre scaricavo un ISO Linux l'altro giorno, e il download è stato interrotto a causa di un singhiozzo wireless.

È stato utile?

Soluzione

Penso che la difficoltà sia determinare come recuperare lo spazio dai file originali.

Penso che potrebbe funzionare quanto segue:

  1. Allocare un file sparse di dimensione combinata.
  2. Copia 100 Mb dalla fine del secondo file alla fine del nuovo file.
  3. Tronca 100 Mb della fine del secondo file
  4. Loop 2 & amp; 3 fino al termine del secondo file (con 2. modificato nella posizione corretta nel file di destinazione).
  5. Fai 2 & amp; 3 & amp; 4 ma con il primo file.

Tutto questo si basa sul supporto dei file sparsi e sul troncamento dei file che libera immediatamente lo spazio.

Se davvero volessi farlo, dovresti esaminare il comando dd . che può eseguire il passaggio di copia

Qualcuno in un'altra risposta ha dato una soluzione ordinata che non richiede file sparsi, ma copia due volte file2:

  1. Copia blocchi da 100Mb dalla fine del file 2 in un nuovo file 3, finendo in ordine inverso. Troncando il file 2 mentre procedi.
  2. Copia blocchi da 100 Mb dalla fine del file 3 nel file 1, finendo con i blocchi nell'ordine originale, alla fine del file 1. Troncando il file 3 mentre procedi.

Altri suggerimenti

tempo impiegato per trovare una soluzione intelligente che coinvolge lo shuffling del settore disco e la manipolazione della catena di file: 2-4 ore

tempo impiegato per acquisire / scrivere software per eseguire la copia e il troncamento sul posto: 2-20 ore

frequenza media programmatore $ 50 / ora: $ 400- $ 1200

costo dell'unità USB da 1 TB: $ 100- $ 200

capacità di comprendere la frase "costo opportunità": impagabile

Ecco un leggero miglioramento rispetto al mio prima risposta .

Se hai 100 MB di spazio libero, copia gli ultimi 100 MB dal secondo file e crea un terzo file. Tronca il secondo file in modo che ora sia più piccolo di 100 MB. Ripeti questo processo fino a quando il secondo file non è stato completamente scomposto in singoli blocchi da 100 MB.

Ora ognuno di quei file da 100 MB può essere aggiunto al primo file, uno alla volta.

Con quei vincoli mi aspetto che dovresti manomettere il file system; modificare direttamente la dimensione del file e i blocchi di allocazione.

In altre parole, dimentica di mescolare qualsiasi blocco di contenuto del file in giro, basta modificare le informazioni su quei file.

se il file è altamente comprimibile (es. registri):

gzip file1

gzip file2

zcat file1 file2 | gzip > file3

rm file1

rm file2

gunzip file3

A rischio di sembrare irriverente, hai considerato l'opzione di ottenere solo un disco più grande? Probabilmente sarebbe più veloce ...

Non molto efficiente, ma penso che possa essere fatto.

Apri il primo file in modalità append e copia i blocchi dal secondo file fino a quando il disco è quasi pieno. Per il resto del secondo file, copia i blocchi dal punto in cui ti sei fermato all'inizio del file tramite I / O ad accesso casuale. Tronca il file dopo aver copiato l'ultimo blocco. Ripeti fino al termine.

Ovviamente, la risposta economica è acquistare più spazio di archiviazione supponendo che sia una possibile risposta. Potrebbe non essere, tuttavia - sistema incorporato senza alcun modo di collegare più spazio di archiviazione, o addirittura nessun accesso all'apparecchiatura stessa - diciamo, sonda spaziale in volo.

La risposta precedentemente presentata basata sul file system sparse è buona (a parte la sua natura distruttiva se qualcosa va storto!) se si dispone di un file system sparse. E se non lo facessi, però?

A partire dalla fine del file 2, copia i blocchi all'inizio del file di destinazione invertendoli mentre procedi. Dopo ogni blocco, il file sorgente viene troncato alla lunghezza non copiata. Ripetere l'operazione per il file n. 1.

A questo punto il file di destinazione contiene tutti i dati all'indietro, i file di origine sono spariti.

Leggi un blocco dalla crostata e dalla fine del file di destinazione, invertili e scrivili nel punto da cui proviene l'altro. Procedi verso l'interno lanciando blocchi.

Al termine, il file di destinazione è la concatenazione dei file di origine. Non sono necessari file system sparsi, non è necessario fare confusione con il file system. Questo può essere effettuato a zero byte liberi poiché i dati possono essere conservati in memoria.

ok, per intrattenimento teorico, e solo se prometti di non perdere tempo a farlo effettivamente:

  • i file sono memorizzati su disco in pezzi
  • i pezzi sono collegati in una catena

Quindi puoi concatenare i file tramite:

  • collegando l'ultimo pezzo del primo file al primo pezzo dell'ultimo file
  • modifica della voce della directory per il primo file per modificare l'ultimo pezzo e le dimensioni del file
  • rimozione della voce della directory per l'ultimo file
  • ripulisce l'eventuale indicatore di fine file del primo file
  • nota che se l'ultimo segmento del primo file è riempito solo parzialmente, dovrai copiare i dati "su" i segmenti dell'ultimo file per evitare la spazzatura nel mezzo del file [grazie @Wedge!]

Questo sarebbe in modo ottimale efficiente: modifiche minime, copia minima, non è necessario spazio sul disco di riserva.

ora vai a comprare un drive USB ;-)

Due pensieri:

Se hai abbastanza RAM fisica, potresti effettivamente leggere il secondo file interamente in memoria, eliminarlo, quindi scriverlo in modalità append sul primo file. Naturalmente se perdi energia dopo aver eliminato ma prima di completare la scrittura, hai perso parte del secondo file per sempre.

Riduci temporaneamente lo spazio su disco utilizzato dalla funzionalità del sistema operativo (ad es. memoria virtuale, "cestino" o simile). Probabilmente solo su Windows.

Dubito che questa sia una risposta diretta alla domanda. Puoi considerarlo come un modo alternativo per risolvere il problema.

Penso che sia possibile considerare il secondo file come parte 2 del primo file. Di solito nell'applicazione zip, vedremmo un file enorme diviso in più parti. Se si apre la prima parte, l'applicazione considererà automaticamente le altre parti in un'ulteriore elaborazione.

Qui possiamo simulare la stessa cosa. Come ha sottolineato @edg, armeggiare il file system sarebbe un modo.

potresti farlo:

head file2 --bytes=1024 >> file1 && tail --bytes=+1024 file2 >file2 

puoi aumentare il 1024 in base a quanto spazio su disco hai, quindi ripeti fino a quando tutti i byte non sono stati spostati.

Questo è probabilmente il modo più veloce per farlo (in termini di tempo di sviluppo)

Potresti riuscire a guadagnare spazio comprimendo l'intero file system. Credo che NTFS supporti questo, e sono sicuro che ci sono versioni di file system * nix che lo supporterebbero. Avrebbe anche il vantaggio di dopo aver copiato i file, avresti ancora più spazio su disco rispetto a quando hai iniziato.

OK, cambiando un po 'il problema. È probabile che ci siano altre cose sul disco che non ti servono, ma non sai di cosa si tratta o dove si trovano. Se potessi trovarlo, potresti eliminarlo, e quindi forse avresti abbastanza spazio extra.

Per trovare questi "tumori", siano essi grandi o piccoli, uso un piccolo programma di campionamento. A partire dalla cima di una directory (o radice) fa due passaggi. Nel passaggio 1, cammina l'albero delle directory, sommando le dimensioni di tutti i file per ottenere un totale di N byte. Nel passaggio 2, cammina di nuovo l'albero delle directory, fingendo di leggere ogni file. Ogni volta che passa N / 20 byte, stampa il percorso della directory e il nome del file che sta "leggendo". Quindi il risultato finale è 20 profondi campioni di nomi di percorso distribuiti uniformemente su tutti i byte nella directory.

Quindi guarda quell'elenco per le cose che mostrano molto che non ti servono e vai via.

(È l'equivalente nello spazio del metodo di campionamento che utilizzo per l'ottimizzazione delle prestazioni.)

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top