2012-05-24 21 views
10

Sto provando, usando bash, a unire il contenuto di un elenco di file (più di 1K) in un file di grandi dimensioni.shell - cat - unire il contenuto dei file in un unico file grande

Ho provato il seguente comando cat:

cat * >> bigfile.txt 

tuttavia ciò che questo comando non fa altro che unire tutto, incluso anche le cose già unite.

ad es. file1.txt

content1 

file2.txt

content2 

file3.txt

content3 

file4.txt

content4 

bigfile.txt

content1 
content2 
content3 
content2 
content3 
content4 
content2 

ma vorrei solo

content1 
content2 
content3 
content4 

all'interno del file .txt

L'altro modo sarebbe cat file1.txt file2.txt ... e così via ... ma non riesco a farlo per più di file 1k!

Grazie per il vostro supporto!

risposta

18

Il problema è che si inserisce bigfile nella stessa directory, rendendolo quindi parte di *. Quindi, qualcosa di simile a

cat dir/* > bigfile 

dovrebbe funzionare come vuoi tu, con i tuoi file fileN.txt ubicati in dir/

+1

... o 'cat *>/tmp/bigfile; mv/tmp/bigfile .'. – tripleee

+0

Penso che fabioln includa intenzionalmente 'bigfile.txt' nell'input; vuole aggiungere al file dai vari 'file * .txt', ma eliminando i duplicati allo stesso tempo. – chepner

+0

Grazie ragazzi. Sì, quello era il problema! Ho messo il bigfile nella stessa dir ... quindi ho usato il comando che mi hai dato (cat dir/*> bigfile)! Solo un'altra domanda: perché metti solo> invece di >> è lo stesso? Grazie! – fabioln79

-3

Prova:

cat `ls -1 *` >> bigfile.txt 

Non ho una macchina UNIX a portata di mano al momento per testarlo prima per te.

+2

-1 Questo non risolve nulla e introduce alcuni nuovi problemi a sé stanti. Non usare 'ls' quando il carattere jolly si espande già nei file che vuoi! Non utilizzare nomi di file non quotati (l'output dai backtick) perché si interrompe se i nomi dei file contengono spazi vuoti. – tripleee

+0

Stavo pensando a un loop quando l'ho scritto, ma non è uscito dalla mia testa correttamente. Comunque, la risposta di Barton mi piace di più. – JerseyMike

4

In seguito alla rilettura della domanda, sembra che si desideri aggiungere dati a bigfile.txt, ma senza aggiungere duplicati. Dovrete passare tutto attraverso sort -u per filtrare i duplicati:

sort -u * -o bigfile.txt 

L'opzione -o per ordinare consente di includere in modo sicuro il contenuto del bigfile.txt nell'input per ordinare prima che il file viene sovrascritto con l'uscita.

EDIT: Supponendo bigfile.txt è ordinato, si può provare un processo in due fasi:

sort -u file*.txt | sort -um - bigfile.txt -o bigfile.txt 

In primo luogo abbiamo ordinare i file di input, rimuovendo i duplicati.Conduciamo quell'output ad un altro processo sort -u, questo usando l'opzione -m2 che dice a sort di unire due file ordinati in precedenza. I due file che verranno uniti sono - (input standard, lo stream proveniente dal primo sort) e bigfile.txt stesso. Usiamo ancora l'opzione -o per permetterci di scrivere l'output su bigfile.txt dopo averlo letto come input.

+0

Ho modificato la risposta per consentire la fusione di nuovi dati in 'bigfile.txt' in modo che rimanga ordinato senza duplicati introdotti. Penso che questo sia il meglio che puoi fare senza passare a un formato più strutturato (come un database). – chepner

4

È possibile mantenere il file di output nella stessa directory, devi solo essere un po 'più sofisticato di *:

shopt -s extglob 
cat !(bigfile.txt) > bigfile.txt 
+0

Grazie. Ho una domanda relativa a questo comando: la directory che contiene il file ha una dimensione di 557 GB, tuttavia il file grande creato ha una dimensione di 495. Non so come spiegarlo. Sto facendo qualcosa di sbagliato? Grazie! – fabioln79

+0

@ fabioln79 Con la quantità di informazioni fornite, si sospetta che ciò potrebbe essere dovuto allo spazio effettivamente utilizzato rispetto alla dimensione del blocco (lettura su quest'ultimo) – user66001

2

L'altro modo sarebbe gatto file1.txt file2.txt .. . e così via ... ma non posso farlo per più di 1k file!

Questo è ciò che è per xargs:

find . -maxdepth 1 -type f -name "file*.txt" -print0 | xargs -0 cat > bigfile.txt 
+0

xargs esegue il comando per * ogni * argomento? In tal caso, dovresti usare ">>" invece di ">"? Sto pensando che quando è fatto, bigfile.txt conterrà solo il contenuto dell'ultimo file passato ad esso. – JerseyMike

+1

xargs esegue il comando una volta per tutti gli argomenti, non è necessario usare ''>>' '. –

+0

Grazie per il chiarimento. La pagina man non mi era chiara. – JerseyMike

1

Questa è una vecchia questione, ma ancora io ti do i file che si desidera concat

un altro approccio con xargs

  1. lista

    ls | grep [modello]> filelist

  2. recensione tuoi file sono nel giusto ordine con vi o cat. Se si utilizza un suffisso (1, 2, 3, ..., N) questo dovrebbe essere alcun problema

  3. Creare il file finale

    cat filelist | xargs cat >> [file finale]

  4. Rimuovere il filelist

    rm -f filelist

Spero che questo aiuti chiunque

Problemi correlati