Łączenie wielu plików tekstowych w jednym pliku w Bash

305

Jaki jest najszybszy i najbardziej pragmatyczny sposób połączenia wszystkich plików * .txt w katalogu w jeden duży plik tekstowy?

Obecnie używam systemu Windows z cygwin, więc mam dostęp do BASH.

Polecenie powłoki systemu Windows też byłoby fajne, ale wątpię, by było takie.

Yada
źródło

Odpowiedzi:

537

To dołącza dane wyjściowe do pliku all.txt

cat *.txt >> all.txt

Spowoduje to zastąpienie pliku all.txt

cat *.txt > all.txt
Robert Greiner
źródło
30
możesz napotkać problem polegający na tym, że cat all.txt do all.txt ... Czasami mam ten problem z grep, nie jestem pewien, czy kot ma takie samo zachowanie.
rmeador
8
@rmeador tak, to prawda, jeśli plik all.txt już istnieje, będziesz miał ten problem. Ten problem rozwiązano przez podanie pliku wyjściowego z innym rozszerzeniem lub przeniesienie pliku all.txt do innego folderu.
Robert Greiner
2
cat * .txt >> tmp; mv tmp all.txt (i upewnij się, że all.txt nie istnieje wcześniej)
Renaud
16
Dostaję „Lista argumentów za długa” - myślę, że nie może obsłużyć ponad 40 000 plików.
Matt
32
Unikaj zbyt długiej listy argumentów, używając:echo *.txt | xargs cat > all.txt
5heikki
145

Pamiętaj tylko, że dla wszystkich podanych dotychczas rozwiązań powłoka decyduje o kolejności łączenia plików. W przypadku Bash, IIRC jest to kolejność alfabetyczna. Jeśli kolejność jest ważna, należy odpowiednio nazwać pliki (01file.txt, 02file.txt itp.) Lub określić każdy plik w kolejności, w której ma być konkatenowany.

$ cat file1 file2 file3 file4 file5 file6 > out.txt
Chinmay Kanchi
źródło
33

Polecenie powłoki systemu Windows typemoże to zrobić:

type *.txt >outputfile

typePolecenie type zapisuje także nazwy plików do stderr, które nie są przechwytywane przez >operatora przekierowania (ale pojawią się na konsoli).

Greg Hewgill
źródło
2
Pamiętaj tylko, że jeśli umieścisz plik wyjściowy w tym samym katalogu, co plik oryginalny, spowoduje to duplikację, ponieważ również połączy nowy plik wyjściowy dwa razy.
CathalMF
26

Do copyłączenia plików można użyć powłoki systemu Windows .

C:\> copy *.txt outputfile

Z pomocy:

Aby dołączyć pliki, określ jeden plik docelowy, ale wiele plików źródłowych (używając symboli wieloznacznych lub formatu plik1 + plik2 + plik3).

Carl Norum
źródło
To, jako najczystsze rozwiązanie IMHO, w zasadzie bez efektów ubocznych, z którymi mogliby się potknąć początkujący, niestety nie jest wystarczająco doceniane :-(
Grmpfhmbl
OP poprosił o Bash.
Big Rich
2
Czy przeczytałeś pytanie? „Polecenie powłoki systemu Windows też byłoby fajne ...”
Carl Norum
8

Uważaj, ponieważ żadna z tych metod nie działa z dużą liczbą plików. Osobiście użyłem tej linii:

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

EDIT: Jak ktoś powiedział w komentarzach, można zastąpić $(ls | grep ".txt")z$(ls *.txt)

EDYCJA: dzięki wiedzy @gnourf_gnourf użycie glob jest właściwym sposobem na iterację plików w katalogu. W związku z tym bluźniercze wyrażenia, takie jak, $(ls | grep ".txt")muszą zostać zastąpione przez *.txt(patrz artykuł tutaj ).

Dobre rozwiązanie

for i in *.txt;do cat $i >> output.txt;done
Jacobe2169
źródło
1
Dlaczego nie for i in $(ls *.txt);do cat $i >> output.txt;done?
streamofstars
2
Obowiązkowe łącze ParsingLs wraz z oceną negatywną (i zasługujesz na więcej niż jedną ocenę negatywną, ponieważ ls | grepjest to bardzo zły antypattern).
gniourf_gniourf
Dostałem ode mnie opinię, ponieważ pozwala na dowolne testowanie / operacje według nazwy pliku przed wyjściem i jest szybki, łatwy i dobry do praktyki. (W moim przypadku chciałem: for i in *; do echo -e "\ n $ i: \ n"; cat $ 1; gotowe)
Nathan Chappell
Czy nie byłoby ls *.txtniepowodzenia, jeśli jest zbyt wiele plików (błąd zbyt długiej listy argumentów)?
Rafael Almeida
6

najbardziej pragmatycznym sposobem korzystania ze skorupy jest polecenie cat. inne sposoby obejmują

awk '1' *.txt > all.txt
perl -ne 'print;' *.txt > all.txt
ghostdog74
źródło
1
To powinna być poprawna odpowiedź w większości przypadków. Jeśli dowolny plik tekstowy bez pustej nowej linii, użycie wszystkich powyższych catmetod połączy ostatnią linię i pierwszą linię z sąsiednich plików.
mootmoot,
6

Co powiesz na to podejście?

find . -type f -name '*.txt' -exec cat {} + >> output.txt
GPrathap
źródło
Ponieważ OP mówi, że pliki znajdują się w tym samym katalogu, może być konieczne dodanie -maxdepth 1do findpolecenia.
codeforester
1
Świetnie współpracuje z dużą liczbą plików, gdzie podejście przyjętym odpowiadać zawodzi
aminy
ah szkoda, że ​​nie wiedziałem, co oznaczają te plus i podwójne przekierowanie ...
hello_earth
To powinna być poprawna odpowiedź. Będzie działał poprawnie w skrypcie powłoki. Oto podobna metoda, jeśli chcesz posortować dane wyjściowe: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]

Na przykład:

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

To weźmie wszystkie pliki TXT w folderze C: \ i zapisze je w folderze C: \ 1 pod nazwą all.txt

Lub

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

Na przykład:

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

To zajmie wszystkie pliki, które są obecne w folderze i umieści tam zawartość w C: \ 1 \ all.txt

Lub ja
źródło
0

Możesz to zrobić w następujący sposób: cat [directory_path]/**/*.[h,m] > test.txt

jeśli użyjesz {}rozszerzenia plików, które chcesz znaleźć, istnieje problem z sekwencjonowaniem.

Michael-Zhang
źródło
0

Gdy napotkasz problem polegający na tym, że cat all.txt do all.txt, możesz spróbować sprawdzić, czy all.txt istnieje, czy nie, jeśli istnieje, usuń

Lubię to:

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

Lew
źródło
cat *.txt > all.txt >polecenie zastępuje plik all.txt, jeśli istnieje, >>dodaje dane do istniejącego pliku
Oleg Bondarenko
-4

wszystko to jest okropne ....

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

łatwe rzeczy.

kSiR
źródło
6
Eeee! Nie rób tego Dofind . -iname "*.txt" -maxdepth 1 -exec cat {} >> out.txt \;
Chinmay Kanchi