Concatenare più file di testo in un singolo file in Bash


305

Qual è il modo più rapido e pragmatico di combinare tutti i file * .txt in una directory in un unico file di testo?

Attualmente sto usando Windows con Cygwin, quindi ho accesso a BASH.

Anche il comando della shell di Windows sarebbe bello, ma dubito che ce ne sia uno.

Risposte:


537

Questo accoda l'output a all.txt

cat *.txt >> all.txt

Questo sovrascrive all.txt

cat *.txt > all.txt

30
potresti imbatterti in un problema in cui gatti all.txt in all.txt ... A volte ho questo problema con grep, non sono sicuro che cat abbia lo stesso comportamento.
dal

8
@rmeador sì, è vero, se all.txt esiste già avrai questo problema. Questo problema viene risolto fornendo al file di output un'estensione diversa o spostando all.txt in una cartella diversa.
Robert Greiner,

2
cat * .txt >> tmp; mv tmp all.txt (e assicurati che all.txt non esista prima)
Renaud

16
Ottengo "Elenco argomenti troppo lungo" - suppongo che non sia in grado di gestire oltre 40.000 file.
Matt,

32
Evita l'elenco delle discussioni troppo a lungo con:echo *.txt | xargs cat > all.txt
5heikki il

145

Ricorda, per tutte le soluzioni fornite finora, la shell decide l'ordine in cui i file sono concatenati. Per Bash, IIRC, è in ordine alfabetico. Se l'ordine è importante, è necessario denominare i file in modo appropriato (01file.txt, 02file.txt, ecc ...) o specificare ogni file nell'ordine in cui si desidera concatenarlo.

$ cat file1 file2 file3 file4 file5 file6 > out.txt

33

Il comando shell di Windows typepuò fare questo:

type *.txt >outputfile

Il typecomando di tipo scrive anche i nomi dei file su stderr, che non vengono acquisiti dall'operatore di >reindirizzamento (ma verranno visualizzati sulla console).


2
Basta essere consapevoli del fatto che se si inserisce il file di output nella stessa directory del file originale, si verificherà una duplicazione perché combinerà anche due volte il nuovo file di output.
CathalMF,

26

È possibile utilizzare la shell di Windows copyper concatenare i file.

C:\> copy *.txt outputfile

Dall'aiuto:

Per aggiungere file, specificare un singolo file per la destinazione, ma più file per l'origine (utilizzando i caratteri jolly o il formato file1 + file2 + file3).


Questa come la soluzione più pulita di IMHO, praticamente senza effetti collaterali su cui i principianti potrebbero inciampare, sfortunatamente non viene apprezzata abbastanza :-(
Grmpfhmbl

OP ha chiesto Bash.
Big Rich

2
Hai letto la domanda? "Anche il comando della shell di Windows sarebbe bello ..."
Carl Norum,

8

Fai attenzione, perché nessuno di questi metodi funziona con un gran numero di file. Personalmente, ho usato questa linea:

for i in $(ls | grep ".txt");do cat $i >> output.txt;done

EDIT: come qualcuno ha detto nei commenti, è possibile sostituire $(ls | grep ".txt")con$(ls *.txt)

EDIT: grazie all'esperienza di @gnourf_gnourf, l'uso di glob è il modo corretto di scorrere i file in una directory. Di conseguenza, espressioni blasfeme come $(ls | grep ".txt")devono essere sostituite da *.txt(vedi l'articolo qui ).

Buona soluzione

for i in *.txt;do cat $i >> output.txt;done

1
Perché no for i in $(ls *.txt);do cat $i >> output.txt;done?
streamofstars,

2
Collegamento obbligatorio di analisi , insieme a un downvote (e meriti più di un downvote, perché ls | grepè un antipattern gravemente negativo).
gniourf_gniourf,

Ho ottenuto un mio voto perché consente test / operazioni arbitrari in base al nome del file prima dell'output ed è veloce, facile e utile per la pratica. (Nel mio caso volevo: per me in *; do echo -e "\ n $ i: \ n"; cat $ 1; fatto)
Nathan Chappell

Non ls *.txtfallirebbe se ci fossero troppi file (errore dell'elenco argomenti troppo lungo)?
Rafael Almeida,

6

il modo più pragmatico con la shell è il comando cat. altri modi includono,

awk '1' *.txt > all.txt
perl -ne 'print;' *.txt > all.txt

1
Questa dovrebbe essere la risposta corretta per la maggior parte delle circostanze. Se qualsiasi file di testo senza una nuova riga vuota, utilizzando tutto il catmetodo sopra concatenerà l'ultima riga e la prima riga dai file adiacenti.
mootmoot,

6

Che ne dici di questo approccio?

find . -type f -name '*.txt' -exec cat {} + >> output.txt

Poiché OP afferma che i file si trovano nella stessa directory, potrebbe essere necessario aggiungere -maxdepth 1al findcomando.
codeforester,

1
Funziona alla grande con un gran numero di file, dove l'approccio della risposta accettata fallisce
ammina il

ah vorrei sapere cosa significano questo plus e doppio reindirizzamento ...
hello_earth

Questa dovrebbe essere la risposta corretta. Funzionerà correttamente in uno script di shell. Ecco un metodo simile se si desidera ordinare l'output:sort -u --output="$OUTPUT_FILE" --files0-from=- < <(find "$DIRECTORY_NAME" -maxdepth 1 -type f -name '*.txt' -print0)
steveH

3
type [source folder]\*.[File extension] > [destination folder]\[file name].[File extension]

Per esempio:

type C:\*.txt > C:\1\all.txt

Ciò prenderà tutti i file txt nella cartella C: \ e li salverà nella cartella C: \ 1 con il nome di all.txt

O

type [source folder]\* > [destination folder]\[file name].[File extension]

Per esempio:

type C:\* > C:\1\all.txt

Ciò richiederà tutti i file presenti nella cartella e li inserirà Contenuto in C: \ 1 \ all.txt


0

Puoi fare così: cat [directory_path]/**/*.[h,m] > test.txt

se si utilizza {}per includere l'estensione dei file che si desidera trovare, c'è un problema di sequenziamento.


0

Quando si verifica un problema a causa del quale gatta all.txt in all.txt, puoi provare a verificare che all.txt sia esistente o meno, se esiste, rimuovi

Come questo:

[ -e $"all.txt" ] && rm $"all.txt"


cat *.txt > all.txt >comando sovrascrive all.txt se esiste >>aggiunge dati al file esistente
Oleg Bondarenko

-4

tutto ciò è brutto ....

ls | grep *.txt | while read file; do cat $file >> ./output.txt; done;

roba facile.


6
Eeek! Non farlo. Dofind . -iname "*.txt" -maxdepth 1 -exec cat {} >> out.txt \;
Chinmay Kanchi,
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.