Il modo più veloce per concatenare i file


25

Ho 10k + file per un totale di oltre 20 GB che devo concatenare in un unico file.

C'è un modo più veloce di

cat input_file* >> out

?

Il modo preferito sarebbe un comando bash, anche Python è accettabile se non notevolmente più lento.


Aggiornato la mia risposta, findnon ordina i file allo stesso modo di una shell glob.
Graeme,

5
Tutte le soluzioni (sane) avranno una velocità equivalente qui poiché il tempo sarà del 99% di I / O di sistema.
Riccioli d'oro


3
Considerando di scrivere il file concatenato su un disco diverso rispetto a quello da cui stai leggendo.
Luis

1
Sarà più veloce se outsi trova su un altro disco.

Risposte:


30

No, il gatto è sicuramente il modo migliore per farlo. Perché usare Python quando esiste un programma già scritto in C per questo scopo? Tuttavia, è possibile che si desideri prendere in considerazione l'utilizzo xargsnel caso in cui la lunghezza della riga di comando superi ARG_MAXe ne occorra più di una cat. Usando gli strumenti GNU, questo equivale a quello che hai già:

find . -maxdepth 1 -type f -name 'input_file*' -print0 |
  sort -z |
  xargs -0 cat -- >>out

1
Puoi assicurarti in questo caso che i tuoi file verranno letti nell'ordine?
Kiwy

1
Sì, perché l'output di findviene reindirizzato sort. Senza questo, i file sarebbero elencati in un ordine arbitrario (definito dal file system, che potrebbe essere un ordine di creazione dei file).
scai

@scai Mi dispiace leggere, con l'ordinamento è abbastanza ovvio
Kiwy

1
@Kiwy, l'unico caso che posso vedere è se le impostazioni locali non sono impostate correttamente nell'ambiente, quindi l'ordinamento potrebbe comportarsi in modo diverso da un bashglob. Altrimenti non vedo alcun caso in cui xargso catnon si comporterebbe come previsto.
Graeme,

3
@MarcvanLeeuwen, xargschiamerà come catè necessario per evitare un errore E2BIG di execve (2).
Stéphane Chazelas,

21

Allocare prima lo spazio per il file di output può migliorare la velocità complessiva poiché il sistema non dovrà aggiornare l'allocazione per ogni scrittura.

Ad esempio, se su Linux:

size=$({ find . -maxdepth 1 -type f -name 'input_file*' -printf '%s+'; echo 0;} | bc)
fallocate -l "$size" out &&
  find . -maxdepth 1 -type f -name 'input_file*' -print0 |
  sort -z | xargs -r0 cat 1<> out

Un altro vantaggio è che se non c'è abbastanza spazio libero, la copia non verrà tentata.

Se questa opzione btrfsè attivata, è possibile utilizzare copy --reflink=alwaysil primo file (che non implica la copia dei dati e sarebbe quindi quasi istantaneo) e aggiungere il resto. Se ci sono 10000 file, probabilmente non farà molta differenza, a meno che il primo file non sia molto grande.

C'è un'API per generalizzare che per ricopiare tutti i file (il BTRFS_IOC_CLONE_RANGE ioctl), ma non sono riuscito a trovare alcuna utilità che esponga tale API, quindi dovresti farlo in C ( pythono in altre lingue purché possano chiamare arbitrari ioctl) .

Se i file di origine sono sparsi o hanno grandi sequenze di caratteri NUL, è possibile creare un file di output sparse (risparmiando tempo e spazio su disco) con (su sistemi GNU):

find . -maxdepth 1 -type f -name 'input_file*' -print0 |
  sort -z | xargs -r0 cat | cp --sparse=always /dev/stdin out

1
@XTian, ​​no, non dovrebbe essere né >>>, ma 1<>come ho detto di scrivere nel file.
Stéphane Chazelas,

5
@grebneke, <>è l'operatore di reindirizzamento read + write standard Bourne / POSIX. Per i dettagli, consultare il manuale della shell o le specifiche POSIX . L'impostazione predefinita fdè 0per l' <>operatore ( <>è l'abbreviazione di 0<>, come <è l'abbreviazione di 0<e >abbreviazione di 1>), quindi è necessario 1reindirizzare esplicitamente stdout. Qui, non è così tanto che abbiamo bisogno di read + write ( O_RDWR), ma che non vogliamo O_TRUNC(come in >) che possa deallocare ciò che abbiamo appena assegnato.
Stéphane Chazelas,

1
@grebneke, unix.stackexchange.com/search?q=user%3A22565+%22%3C%3E%22 te ne darà alcuni. ksh93 ha operatori di ricerca BTW, e puoi cercare avanti con ddo tramite lettura.
Stéphane Chazelas,

1
@StephaneChazelas - grazie mille, il tuo aiuto e conoscenza sono molto apprezzati!
Grebneke,

1
Non sono convinto che ci saranno molti casi in cui fallocatesi annullerà il sovraccarico dell'extra find, anche se sarà più veloce la seconda volta. btrfscertamente apre alcune interessanti possibilità però.
Graeme
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.