Łączenie plików i wstawianie nowego wiersza między plikami

127

Mam wiele plików, z którymi chcę się połączyć cat. Powiedzmy

File1.txt 
foo

File2.txt
bar

File3.txt
qux

Chcę konkatować, aby ostateczny plik wyglądał następująco:

foo

bar

qux

Zamiast tego ze zwykłym cat File*.txt > finalfile.txt

foo
bar 
qux

Jak to zrobić we właściwy sposób?

neversaint
źródło

Odpowiedzi:

121

Możesz to zrobić:

for f in *.txt; do (cat "${f}"; echo) >> finalfile.txt; done

Upewnij się, że plik finalfile.txtnie istnieje, zanim uruchomisz powyższe polecenie.

Jeśli masz prawo do korzystania awk, możesz:

awk 'FNR==1{print ""}1' *.txt > finalfile.txt
codaddict
źródło
10
AWK '{print $0}' *.txt
licznik czasu
7
Ma to wyraźną wadę polegającą na tym, że na końcu (od pierwszej możliwości) lub na początku (druga alternatywa) będą puste linie. Możesz jednak łatwo ustrzec się przed tym, używając awk 'FNR==1 && NR > 1 ...'zamiast tego.
tripleee
5
Jeśli umieścisz >finalfile.txtpo done, możesz nadpisać zamiast dołączać, co usunie wymóg upewnienia się, że przed pętlą brakuje pliku lub jest on pusty.
tripleee
53

Jeśli masz wystarczająco dużo plików, które możesz wyświetlić każdy z nich, możesz użyć podstawiania procesów w Bash, wstawiając nowy wiersz między każdą parą plików:

cat File1.txt <(echo) File2.txt <(echo) File3.txt > finalfile.txt
Robert Tupelo-Schneck
źródło
1
Piękny! Dzięki.
Bob Kocisko
Pomogło mi to w przypadku moich certyfikatów Letsencrypt do tworzenia plików .pem.
leeman24
35

Gdybym to robił, użyłbym seda:

sed -e '$s/$/\n/' -s *.txt > finalfile.txt

W tym wzorcu sed $ ma dwa znaczenia, po pierwsze dopasowuje tylko numer ostatniej linii (jako zakres linii do zastosowania wzorca), a po drugie dopasowuje koniec linii we wzorcu podstawiania.

Jeśli twoja wersja seda nie ma -s(przetwarzaj pliki wejściowe osobno), możesz to wszystko zrobić w pętli:

for f in *.txt ; do sed -e '$s/$/\n/' $f ; done > finalfile.txt
Flexo
źródło
3
Lub w GNU sed:sed -s '$G' *.txt > finalfile.txt
Ruud Helderman
Tylko jeden strumień! to powinna być zaakceptowana odpowiedź!
Yassine ElBadaoui
uważajcie ludzie, właśnie zawiesiłem komputer, ponieważ użyłem go findzamiast *.txt, co oznaczało, że plik został dołączony do siebie!
Xerus
11

Możesz to zrobić używając, xargsjeśli chcesz, ale główna idea jest taka sama:

find *.txt | xargs -I{} sh -c "cat {}; echo ''" > finalfile.txt
Nick Roz
źródło
1
Dzięki. Uważam, że jest xargsdużo łatwiejszy w użyciu niż pętle w bashu.
RawwrBag
9

Działa to w Bash:

for f in *.txt; do cat $f; echo; done

W przeciwieństwie do odpowiedzi z >>(dołącz), dane wyjściowe tego polecenia mogą być przesłane potokiem do innych programów.

Przykłady:

  • for f in File*.txt; do cat $f; echo; done > finalfile.txt
  • (for ... done) > finalfile.txt (pareny są opcjonalne)
  • for ... done | less (rury w mniej)
  • for ... done | head -n -1 (to usuwa końcową pustą linię)
user3780389
źródło
7

Tak właśnie zrobiłem to na OsX 10.10.3

for f in *.txt; do (cat $f; echo '') >> fullData.txt; done

ponieważ proste polecenie „echo” bez parametrów zakończyło się brakiem wstawienia nowych wierszy.

lbrutti
źródło
Spowoduje to umieszczenie ciągu na końcu pliku; jak wstawić go między każdy plik?
onassar
3

W Pythonie łączy się to z pustymi wierszami między plikami ( ,zapobiega dodawaniu dodatkowego końcowego pustego wiersza):

print '\n'.join(open(f).read() for f in filenames),

Oto brzydka jedna linijka Pythona, którą można wywołać z powłoki i wypisuje dane wyjściowe do pliku:

python -c "from sys import argv; print '\n'.join(open(f).read() for f in argv[1:])," File*.txt > finalfile.txt
user3780389
źródło