Объединение файлов и вставка новой строки между файлами

127

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

File1.txt 
foo

File2.txt
bar

File3.txt
qux

Я хочу объединить, чтобы окончательный файл выглядел так:

foo

bar

qux

Вместо этого с обычным cat File*.txt > finalfile.txt

foo
bar 
qux

Как правильно это сделать?

neversaint
источник

Ответы:

121

Ты можешь сделать:

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

Убедитесь, что файл finalfile.txt запуском указанной выше команды не существует.

Если вам разрешено использовать, awkвы можете:

awk 'FNR==1{print ""}1' *.txt > finalfile.txt
codaddict
источник
10
AWK '{print $0}' *.txt
Timger
7
Его явный недостаток состоит в том, что будут пустые строки либо в конце (из первого варианта), либо в начале (второй вариант). Однако вы можете легко защититься от этого с помощью awk 'FNR==1 && NR > 1 ...'.
Tripleee
5
Если вы поставите >finalfile.txtпосле, doneвы можете перезаписать вместо добавления, что уберет требование убедиться, что файл отсутствует или пуст перед циклом.
Tripleee
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 (это удаляет конечную пустую строку)
user3780389
источник
7

Вот так я только что сделал на OsX 10.10.3

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

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

lbrutti
источник
Это помещает строку в конец файла; как мне вставить его между каждым файлом?
onassar
3

В python это объединяется с пустыми строками между файлами ( ,подавляет добавление дополнительной конечной пустой строки):

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

Вот уродливый однострочник Python, который можно вызвать из оболочки и распечатать вывод в файл:

python -c "from sys import argv; print '\n'.join(open(f).read() for f in argv[1:])," File*.txt > finalfile.txt
user3780389
источник