Jak dołączyć zawartość wielu plików do jednego pliku

174

Chcę skopiować zawartość pięciu plików do jednego pliku bez zmian. Próbowałem to zrobić, używając cp dla każdego pliku. Ale to nadpisuje zawartość skopiowaną z poprzedniego pliku. Ja też próbowałem

paste -d "\n" 1.txt 0.txt

i to nie zadziałało.

Chcę, aby mój skrypt dodawał nową linię na końcu każdego pliku tekstowego.

na przykład. Pliki 1.txt, 2.txt, 3.txt. Umieść zawartość 1, 2, 3 w 0. txt

Jak mam to zrobić ?

Parowy
źródło

Odpowiedzi:

308

Potrzebujesz polecenia cat(skrót od concatenate) z przekierowaniem powłoki ( >) do pliku wyjściowego

cat 1.txt 2.txt 3.txt > 0.txt
radykalny7
źródło
8
powinno być >> prawda? a także dlaczego przed całym tekstem w moim pliku 0.txt znajduje się nowa linia?
Steam
1
czy chcesz zachować zawartość 0.txt?
2013
13
@blasto to zależy. Możesz użyć, >>aby dołączyć jeden plik do drugiego, gdzie > nadpisuje plik wyjściowy tym, co jest do niego skierowane. A jeśli chodzi o znak nowej linii, czy istnieje znak nowej linii jako pierwszy znak w pliku 1.txt? Możesz się tego dowiedzieć, używając od -ci sprawdzając, czy pierwsza postać to \n.
radykalny7
1
@ RADYKAL7 Dzięki. Właściwie moje pliki są takie jak foo_1, foo_2, foo_3. Próbowałem zmodyfikować twój kod jako - cat "$ filename _" {1,2,3} ". Txt", ale to nie zadziałało.
Steam
1
@blasto Zdecydowanie zmierzasz we właściwym kierunku. Bash z pewnością akceptuje formularz {...}dopasowywania nazw plików, więc może cudzysłowy trochę pomieszały w twoim skrypcie? Zawsze staram się pracować z takimi rzeczami, używając lspowłoki. Kiedy dobrze wykonuję polecenie, po prostu wycinam je i wklejam do skryptu, tak jak jest. Ta -xopcja może być również przydatna w skryptach - przed wykonaniem wyświetli ona rozwinięte polecenia w skrypcie.
radykalne 7
97

Inną opcją dla tych z Was, którzy nadal natkną się na ten post, tak jak ja, jest użycie find -exec:

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

W moim przypadku potrzebowałem bardziej niezawodnej opcji, która przeglądałaby wiele podkatalogów, więc zdecydowałem się użyć find. Rozbijając to:

find .

Zajrzyj do bieżącego katalogu roboczego.

-type f

Interesują mnie tylko pliki, a nie katalogi itp.

-name '*.txt'

Zmniejsz wynik ustawiony według nazwy

-exec cat {} +

Wykonaj polecenie cat dla każdego wyniku. „+” oznacza, że catzostało utworzone tylko 1 wystąpienie (thx @gniourf_gniourf)

 >> output.file

Jak wyjaśniono w innych odpowiedziach, dołącz zawartość kategorii na końcu pliku wyjściowego.

mopo922
źródło
10
Ta odpowiedź ma wiele błędów. Po pierwsze, znak wieloznaczny *.txtmusi być cytowany (w przeciwnym razie całe findpolecenie, tak jak napisano, jest bezużyteczne). Kolejna wada wynika z rażącego nieporozumienia: polecenie, które jest wykonywane, to nie cat >> 0.txt {} , ale cat {}. Twoje polecenie jest w rzeczywistości równoważne z { find . -type f -name *.txt -exec cat '{}' \; ; } >> 0.txt(dodałem grupowanie, abyś wiedział, co się naprawdę dzieje). Inną wadą jest to, że findznajdzie plik 0.txti catbędzie narzekać, mówiąc, że plik wejściowy jest plikiem wyjściowym .
gniourf_gniourf
Dzięki za poprawki. Mój przypadek był trochę inny i nie pomyślałem o niektórych z tych pułapek zastosowanych w tym przypadku.
mopo922
Powinieneś umieścić >> output.filena końcu swoje polecenie, aby nikogo (w tym siebie) nie skłonić do myślenia, że findzostanie wykonany cat {} >> output.filedla każdego znalezionego pliku.
gniourf_gniourf
Zaczynam wyglądać naprawdę dobrze! Ostatnia sugestia: użyj -exec cat {} +zamiast -exec cat {} \;, tak aby tylko jedna instancja catbyła tworzona z kilkoma argumentami ( +jest określona przez POSIX ).
gniourf_gniourf
3
Dobra odpowiedź i słowo ostrzeżenia - zmodyfikowałem swoje na: find . -type f -exec cat {} + >> outputfile.txti nie mogłem zrozumieć, dlaczego mój plik wyjściowy nie przestał rosnąć w koncerty, mimo że katalog miał tylko 50 megabajtów. To dlatego, że ciągle dołączałem do siebie plik outputfile.txt! Więc po prostu upewnij się, że nazwa tego pliku jest poprawna lub umieść go całkowicie w innym katalogu, aby tego uniknąć.
Thisisstackoverflow
43

jeśli masz określony typ wyjścia, zrób coś takiego

cat /path/to/files/*.txt >> finalout.txt
Eswar Yaganti
źródło
1
Pamiętaj jednak, że tracisz możliwość zachowania kolejności scalania. Może to mieć wpływ na ciebie, jeśli masz swoje pliki o nazwach, np. file_1,, file_2file_11, Ze względu na naturalną kolejność sortowania plików.
emix
16

Jeśli wszystkie twoje pliki znajdują się w jednym katalogu, możesz po prostu to zrobić

cat * > 0.txt

Pliki 1.txt, 2.txt, .. przejdą do 0.txt

Pooja
źródło
Już odpowiedział Eswar. Pamiętaj jednak, że tracisz możliwość zachowania kolejności scalania. Może to mieć wpływ na ciebie, jeśli masz swoje pliki o nazwach, np. file_1,, file_2file_11, Ze względu na naturalną kolejność sortowania plików.
emix
10
for i in {1..3}; do cat "$i.txt" >> 0.txt; done

Znalazłem tę stronę, ponieważ potrzebowałem połączyć razem 952 plików w jeden. Okazało się, że działa to znacznie lepiej, jeśli masz wiele plików. Spowoduje to wykonanie pętli dla dowolnej liczby liczb, których potrzebujesz, i umieszczenie każdej z nich za pomocą >>, aby dołączyć do końca 0.txt.

freddythunder
źródło
możesz użyć rozwinięcia nawiasów klamrowych w bash, aby napisać cat {1,2,3} .txt >> 0.txt
mcheema
9

Jeśli wszystkie twoje pliki mają podobne nazwy, możesz po prostu zrobić:

cat *.log >> output.log
AeaRy
źródło
5

Inną opcją jest sed:

sed r 1.txt 2.txt 3.txt > merge.txt 

Lub...

sed h 1.txt 2.txt 3.txt > merge.txt 

Lub...

sed -n p 1.txt 2.txt 3.txt > merge.txt # -n is mandatory here

Lub bez przekierowania ...

sed wmerge.txt 1.txt 2.txt 3.txt

Zauważ, że ostatnia linia również merge.txt(nie wmerge.txt!) Możesz użyć, w"merge.txt"aby uniknąć pomyłki z nazwą pliku i -ndo cichego wyjścia.

Oczywiście możesz również skrócić listę plików za pomocą symboli wieloznacznych. Na przykład w przypadku plików numerowanych, jak w powyższych przykładach, zakres nawiasów można określić w następujący sposób:

sed -n w"merge.txt" {1..3}.txt
Fran
źródło
4

jeśli twoje pliki zawierają nagłówki i chcesz je usunąć z pliku wyjściowego, możesz użyć:

for f in `ls *.txt`; do sed '2,$!d' $f >> 0.out; done
brunocrt
źródło
3

Jeśli oryginalny plik zawiera znaki niedrukowalne, zostaną one utracone podczas korzystania z polecenia cat. Używając „cat -v”, elementy niedrukowalne zostaną przekonwertowane na widoczne ciągi znaków, ale plik wyjściowy nadal nie będzie zawierał rzeczywistych znaków niedrukowalnych w oryginalnym pliku. Przy małej liczbie plików alternatywą może być otwarcie pierwszego pliku w edytorze (np. Vim), który obsługuje znaki niedrukowalne. Następnie przejdź do końca pliku i wpisz „: r nazwa_drugi_pliku”. Spowoduje to pobranie drugiego pliku, w tym znaków niedrukowalnych. To samo można zrobić dla dodatkowych plików. Po wczytaniu wszystkich plików wpisz „: w”. W rezultacie pierwszy plik będzie teraz zawierał to, co robił pierwotnie, oraz zawartość plików, które zostały wczytane.

BACooper
źródło
To nie jest łatwe do skryptu.
FKEinternet
1

Jeśli chcesz dołączyć zawartość 3 plików do jednego pliku, dobrym wyborem będzie następujące polecenie:

cat file1 file2 file3 | tee -a file4 > /dev/null

Połączy zawartość wszystkich plików w plik4, zrzucając dane wyjściowe konsoli do /dev/null.

Ajit K'sagar
źródło