Qual è il modo migliore per unire nuovamente i file dopo averli divisi?


73

Se ho un file di grandi dimensioni e devo dividerlo in blocchi da 100 megabyte, lo farò

split -b 100m myImage.iso

Questo di solito mi dà qualcosa di simile

xaa
xab
xac
xad

E per rimetterli insieme ho usato

cat x* > myImage.iso

Sembra che ci dovrebbe essere un modo più efficiente di leggere ogni riga di codice in un gruppo di file con cate reindirizzare l'output su un nuovo file. Come un modo per aprire solo due file, rimuovere il EOFmarker dal primo e collegarli, senza dover passare attraverso tutti i contenuti.

Windows / DOS ha un comando di copia per i file binari. La guida menziona che questo comando è stato progettato per essere in grado di combinare più file. Funziona con questa sintassi: ( /bè per la modalità binaria)

copy /b file1 + file2 + file3 outputfile

Esiste qualcosa di simile o un modo migliore per unire file di grandi dimensioni su Linux rispetto a cat?

Aggiornare

Sembra che catsia in effetti il ​​modo giusto e il modo migliore per unire i file. Sono contento di sapere che stavo usando il comando giusto da sempre :) Grazie a tutti per il vostro feedback.


22
Nota a margine: meglio non usarlo cat x*, perché l'ordine dei file dipende dalle impostazioni locali. Meglio iniziare a digitare cat x, che premere Esc e quindi *: vedrai l'ordine espanso dei file e puoi riorganizzare.
rozcietrzewiacz,

16
Invece di cat x*te potresti prendere in considerazione l'espansione delle parentesi graffe, cat xa{a..g}che espande la sequenza specificata in cat xaa xab xac xad xae xaf xag
Peter.O

3
@rozcietrzewiacz - puoi fare un esempio di come modificherei le impostazioni della mia locale che non funzionerebbero cat x*? Anche le nuove impostazioni locali non influirebbero in splitmodo tale che se splite cat x*fossero utilizzate sullo stesso sistema funzionerebbero sempre?
Cwd,

3
"aprendo due file, rimuovendo il marcatore EOF dal primo e collegandoli senza dover passare attraverso tutti i contenuti." ... sembra che tu debba inventare un nuovo filesystem per fare quello che vuoi
JoelFan

6
@cwd: Esaminando split.cin GNU Coreutils, i suffissi sono costruiti da una matrice fissa di caratteri: static char const *suffix_alphabet = "abcdefghijklmnopqrstuvwxyz";. Il suffisso non sarebbe influenzato dalla locale. (Ma non credo che nessun locale sano possa riordinare le lettere minuscole; anche EBCDIC mantiene il suo ordine standard.)
Keith Thompson

Risposte:


50

Questo è proprio ciò per cui è catstato creato. Dal momento che è uno dei più antichi strumenti GNU, penso sia molto improbabile che qualsiasi altro strumento lo faccia più velocemente / meglio. E non è il piping - sta solo reindirizzando l'output.


Il cat x, then press Esctrucco che hai citato è pulito .. Ho cercato qualcosa del genere, grazie ... buon commento e buona risposta
Peter.O

2
Prego :) Inoltre, quando hai quell'elenco di file sulla riga di comando, puoi usare Ctrl+Wper ritagliare una parola e poi Ctrl+Yincollarla.
rozcietrzewiacz,

gatto significa "concatenare"
JoelFan

4
.. e "catenate" derrive da una parola latina "catena" che significa "una catena" .. concatenare sta unendo le maglie di una catena. ... (e un po 'più fuori tema, una curva catenaria deriva anche da "catena". È il modo in cui pende una catena)
Peter.O

19

Sotto il cappuccio

Non c'è modo più efficiente di copiare il primo file, quindi di copiare il secondo file dopo di esso e così via. Sia DOS copyche catfarlo.

Ogni file è memorizzato indipendentemente dagli altri file sul disco. Quasi tutti i filesystem progettati per archiviare i dati su un dispositivo simile a un disco funzionano a blocchi. Ecco una presentazione altamente semplificata di ciò che accade: il disco è diviso in blocchi di, diciamo 1kB, e per ogni file il sistema operativo memorizza l'elenco dei blocchi che lo compongono. La maggior parte dei file non sono lunghi un numero intero di blocchi, quindi l'ultimo blocco è occupato solo parzialmente. In pratica, i filesystem hanno molte ottimizzazioni, come la condivisione dell'ultimo blocco parziale tra più file o la memorizzazione di "blocchi da 46798 a 47913" anziché "blocco 46798, blocco 46799, ...". Quando il sistema operativo deve creare un nuovo file, cerca blocchi gratuiti. I blocchi non devono essere consecutivi: se solo i blocchi 4, 5, 98 e 178 sono gratuiti, è comunque possibile memorizzare un file da 4kB.

Potresti supportare blocchi parziali a metà file, ma ciò aggiungerebbe una notevole complessità, in particolare quando accedi ai file in modo non sequenziale: per saltare al 10340 ° byte, non potresti più saltare al 100 ° byte dell'11 ° blocco, avresti per verificare la lunghezza di ogni blocco intermedio.

Dato l'uso dei blocchi, non puoi semplicemente unire due file, perché in generale il primo file termina a metà blocco. Certo, potresti avere un caso speciale, ma solo se vuoi eliminare entrambi i file durante la concatenazione. Sarebbe una gestione altamente specifica per un'operazione rara. Tale gestione speciale non vive da sola, perché su un tipico filesystem si accede a molti file contemporaneamente. Quindi, se vuoi aggiungere un'ottimizzazione, devi pensare attentamente: cosa succede se qualche altro processo sta leggendo uno dei file coinvolti? Cosa succede se qualcuno cerca di concatenare A e B mentre qualcuno sta concatenando A e C? E così via. Tutto sommato, questa rara ottimizzazione sarebbe un enorme onere.

Tutto sommato, non è possibile rendere più efficiente l'unione dei file senza fare grandi sacrifici altrove. Non ne vale la pena.

Sulla scissione e l'unione

splite catsono semplici modi per dividere e unire i file. splitsi occupa della produzione di file denominati in ordine alfabetico, in modo che cat *funzioni per unirsi.

Un aspetto negativo di catunirsi è che non è robusto rispetto alle comuni modalità di errore. Se uno dei file viene troncato o mancante, catnon si lamenterà, otterrai solo un output danneggiato.

Esistono utility di compressione che producono archivi multipart, come zipsplite rar -v. Non sono molto univoci, perché comprimono e comprimono (assemblano più file in uno) oltre a dividere (e al contrario decomprimere e decomprimere oltre a unirsi). Ma sono utili in quanto verificano che tu abbia tutte le parti e che le parti siano complete.


8

Sembra che ci dovrebbe essere un modo più efficiente rispetto al piping di tutti i contenuti attraverso il sistema stdin/stdout

Solo che non è proprio quello che sta succedendo. La shell sta collegando lo stdout cat direttamente al file aperto, il che significa che "passare attraverso stdout" è lo stesso che scrivere su disco.


Stavo solo immaginando di usare cat per visualizzare diversi gigabyte di codice nella console, quindi averlo catturato e messo in un file. Questa è l'immagine mentale che ho per quello che deve accadere quando uso cat e reindirizzo l'output che non riesco a vedere. Sembrava che ci fosse un modo per aprire due file, collegarli e poi chiuderli sarebbe più efficiente che passare attraverso tutte le righe di codice cat. Grazie per avermi informato della connessione diretta.
Cwd,

@cwd Sarebbe possibile progettare un filesystem in cui si possano unire due file in quel modo, ma ciò complicherebbe immensamente la progettazione del filesystem. Ottimizzeresti per quell'unica operazione al costo di rendere molte attività comuni più complicate e più lente.
Gilles 'SO- smetti di essere malvagio' il

@Gilles - sarebbe interessante sapere di più sui dettagli di basso livello. Per me, leggere tutti i settori dal disco rigido per diversi file e poi scaricarli in altri settori inutilizzati sul disco sembra inefficiente. E penso che i file di grandi dimensioni debbano essere archiviati su più blocchi di settori liberi a volte perché potrebbero non esserci sempre abbastanza blocchi affiancati per archiviarli. Pertanto, teoricamente, è possibile unire i file in uno rimuovendo il marker EOF e puntando a un gruppo di settori all'inizio del file successivo. * nix è potente, quindi mi chiedevo se ci fosse un modo migliore di cat.
Cwd,

@cwd Non esiste un "marker EOF". Nessun filesystem moderno e sano funziona in questo modo, perché impedisce che alcuni caratteri si verifichino nei file (oppure richiede codifiche complesse). Ma anche se ci fosse un marcatore EOF, il più delle volte, non avresti il ​​file giusto dopo di esso.
Gilles 'SO- smetti di essere malvagio' il

Intendevo il concetto del marker EOF e non un marker EOF reale. Altrimenti, se guardi i bit e i byte di un file sul disco rigido, come fai a sapere dove finisce? Si specifica la lunghezza del file all'inizio di esso? Sto parlando di una cosa di livello davvero basso. È quello a cui ti riferisci?
Cwd,

3

Una volta ho avuto esattamente questo problema: volevo unire alcuni file, ma non avevo abbastanza spazio su disco per tenerli doppiamente.

Quindi ho scritto un sacco di programmi:

  • uno per "succhiare" un file leggendolo, inviandolo a stdout e, se finito, rimuovendolo
  • e uno per bufferizzare i dati "al volo".

Questo mi ha permesso di fare qualcosa del genere

partto sourcefile | mybuffer 128M >>cumufile

e quindi rimuovendo il file sorgente mentre 128M era ancora non scritto. Un po 'pericoloso, ma se i dati non sono così preziosi, o esistono anche altrove, è fattibile.

Se necessario, posso fornire la fonte.


0

Tecnicamente parlando, questo è un modo per accedere all'intero file senza dover leggere e scrivere l'intero contenuto e potrebbe essere utile per file di grandi dimensioni o se c'è poco spazio:

$ mkfifo myImage.iso
$ cat xa{a..g} > myImage.iso &

E poi usa myImage.iso, per esempio

$ md5sum myImage.iso

Anche se ovviamente myImage.isoè un file speciale (chiamato pipe) e non un file normale, quindi questo può essere utile o no a seconda di ciò che stai cercando di fare.


0

Suddivisione dei file

Dividi per dimensione

Se si desidera dividere file di grandi dimensioni in file di piccole dimensioni e scegliere il nome e la dimensione dei file di output di piccole dimensioni, questo è il modo.

split -b 500M videos\BigVideoFile.avi SmallFile.

In questo modo si sceglie di dividere un file grande in parti più piccole di 500 MB. Inoltre, si desidera che i nomi dei file di parti siano SmallFile. Si noti che è necessario punto dopo il nome del file. Il risultato dovrebbe essere la generazione di nuovi file come questo:

SmallFile.ab SmallFile.ad SmallFile.af SmallFile.ah SmallFile.aj
SmallFile.aa SmallFile.ac SmallFile.ae SmallFile.ag SmallFile.ai SmallFile.ak
...

Dividi per numero di linee

In questo modo dividerai il file testuale in file più piccoli limitati a 50 righe.

split -l 50 text_to_split.txt

Il risultato dovrebbe essere qualcosa del genere:

xaa xab xac ...

Dividi per byte

Dividi in piccoli file con dimensioni personalizzate di piccoli file in byte:

split -b 2048 BigFile.mp4

Il risultato dovrebbe essere simile al risultato della divisione per numero di linee .

Partecipazione ai file

Puoi unire i file in due modi. Il primo è:

cat SmallFile.* > OutputBigVideoFile.avi

o con:

cat SmallFile.?? > OutputBigVideoFile.avi

Nota: quando si uniscono file, i file di piccole dimensioni non devono essere danneggiati. Inoltre, tutti i file di piccole dimensioni (parte) devono trovarsi nella stessa directory.

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.