Об’єднання файлів і вставте новий рядок між файлами


127

У мене є кілька файлів, з якими я хочу сформулюватись cat. Скажімо

File1.txt 
foo

File2.txt
bar

File3.txt
qux

Я хочу сформулювати так, щоб кінцевий файл виглядав так:

foo

bar

qux

Замість цього зі звичайним cat File*.txt > finalfile.txt

foo
bar 
qux

Який правильний спосіб це зробити?


Відповіді:


121

Ви можете зробити:

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

Переконайтесь, що файл finalfile.txtне існує, перш ніж запустити вищевказану команду.

Якщо вам дозволено використовувати, awkви можете:

awk 'FNR==1{print ""}1' *.txt > finalfile.txt

10
AWK '{print $0}' *.txt
таймер

7
Це має чіткий недолік у тому, що порожні рядки будуть або в кінці (від першої альтернативи), або на початку (друга альтернатива). awk 'FNR==1 && NR > 1 ...'Однак ви можете легко захиститись від цього .
трійка

5
Якщо ви поставите >finalfile.txtпісля цього, doneви можете перезаписати замість додавання, що видалить вимогу переконатися, що файл відсутній чи порожній перед циклом.
трійка

53

Якщо у вас є достатньо файлів, на яких ви можете перелічити кожен, ви можете використовувати підстановку процесу в Bash, вставляючи новий рядок між кожною парою файлів:

cat File1.txt <(echo) File2.txt <(echo) File3.txt > finalfile.txt

1
Гарний! Дякую.
Боб Кочисько

Це добре працювало для мене на моїх сертах Letsencrypt для створення .pem файлів.
leeman24

35

Якби це я робив, я би використовував sed:

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

У цьому шаблоні sed $ $ має два значення, по-перше, він відповідає лише номеру останнього рядка (як діапазон рядків, на який слід застосувати шаблон), а по-друге, він відповідає кінці рядка в схемі заміщення.

Якщо у вашій версії sed немає -s(обробляйте вхідні файли окремо), все це можна зробити як цикл:

for f in *.txt ; do sed -e '$s/$/\n/' $f ; done > finalfile.txt

3
Або в GNU sed:sed -s '$G' *.txt > finalfile.txt
Рууд Гельдерман

Тільки один потік! це має бути прийнята відповідь!
Яссін ЕльБадауі

будьте обережні хлопці, я просто зірвав свій комп'ютер, тому що я використав findзамість цього *.txt, що означало, що файл був доданий до себе!
Xerus

11

Ви можете це зробити, використовуючи, xargsякщо вам подобається, але основна ідея все одно та сама:

find *.txt | xargs -I{} sh -c "cat {}; echo ''" > finalfile.txt

1
Дякую. Я вважаю xargsнабагато простіше у використанні, ніж петлі в bash.
RawwrBag

9

Це працює в Bash:

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

На відміну від відповідей з >>(додавати), вихід цієї команди може бути переданий в інші програми.

Приклади:

  • for f in File*.txt; do cat $f; echo; done > finalfile.txt
  • (for ... done) > finalfile.txt (паролі необов’язкові)
  • for ... done | less (обшивка менше)
  • for ... done | head -n -1 (це знімає проміжну порожню лінію)

7

Ось як я це робив на OsX 10.10.3

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

оскільки проста команда 'echo' без параметів не вставила жодних нових рядків.


Це ставить рядок у кінці файлу; як я можу вставити його між кожним файлом?
onassar

3

У python це з'єднується з порожніми рядками між файлами ( ,придушує додавання додаткового останнього порожнього рядка):

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

Ось некрасивий однолінійний пітон, який можна викликати з оболонки та друкує вихід у файл:

python -c "from sys import argv; print '\n'.join(open(f).read() for f in argv[1:])," File*.txt > finalfile.txt
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.