Как добавить содержимое нескольких файлов в один файл


174

Я хочу скопировать содержимое пяти файлов в один файл как есть. Я пытался сделать это с помощью cp для каждого файла. Но это перезаписывает содержимое, скопированное из предыдущего файла. Я тоже пробовал

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

и это не сработало.

Я хочу, чтобы мой скрипт добавлял новую строку в конце каждого текстового файла.

например. Файлы 1.txt, 2.txt, 3.txt. Поместите содержимое 1,2,3 в 0.txt

Как мне это сделать ?


1
возможный дубликат объединения файлов и вставка новой строки между файлами
Никос С.

Другой ответ здесь: stackoverflow.com/questions/2576693/…
Никос С.

Ответы:


308

Вам нужна команда cat(сокращение от конкатенации) с перенаправлением оболочки ( >) в ваш выходной файл

cat 1.txt 2.txt 3.txt > 0.txt

8
должно быть >> верно? а также почему перед моим текстом 0.txt стоит новая строка?
Steam

1
Вы хотите сохранить содержимое 0.txt?
Сех

13
@blasto это зависит. Вы можете использовать >>для добавления одного файла в другой, где > перезаписывает выходной файл с тем, что направлено в него. Что касается новой строки, есть ли новая строка в качестве первого символа в файле 1.txt? Вы можете узнать с помощью od -cи посмотреть, является ли первый символ \n.
радикал7

1
@ radical7 Спасибо. На самом деле мои файлы похожи на foo_1, foo_2, foo_3. Я пытался изменить ваш код как - cat "$ filename _" {1,2,3} ". Txt", но это не сработало.
Steam

1
@blasto Вы определенно движетесь в правильном направлении. Bash определенно принимает форму {...}для сопоставления имен файлов, так что, возможно, кавычки немного запутали ваш скрипт? Я всегда стараюсь работать с такими вещами, используя это lsв оболочке. Когда я правильно понял команду, я просто вырезал и вставил ее в скрипт как есть. Вы также можете найти эту -xопцию полезной в ваших скриптах - она ​​будет отображать расширенные команды в скрипте перед выполнением.
радикал7

97

Другой вариант, для тех из вас, кто все еще натыкается на этот пост, как я, это использовать find -exec:

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

В моем случае мне понадобился более надежный вариант, который просматривал бы несколько подкаталогов, поэтому я решил использовать find. Разбивая это:

find .

Посмотрите в текущем рабочем каталоге.

-type f

Интересуют только файлы, а не каталоги и т. Д.

-name '*.txt'

Урезать результат, установленный по имени

-exec cat {} +

Выполните команду cat для каждого результата. «+» означает, что catсоздается только 1 экземпляр (thx @gniourf_gniourf)

 >> output.file

Как объяснено в других ответах, добавьте содержимое в конце выходного файла.


10
В этом ответе много недостатков. Во-первых, подстановочный знак *.txtдолжен быть заключен в кавычки (в противном случае вся findкоманда, как написано, бесполезна). Другим недостатком является грубое заблуждение: выполняемая команда - нет cat >> 0.txt {} , но cat {}. Ваша команда фактически эквивалентна { find . -type f -name *.txt -exec cat '{}' \; ; } >> 0.txt(я добавил группировку, чтобы вы поняли, что на самом деле происходит). Другим недостатком является то, что findон найдет файл 0.txtи catбудет жаловаться, говоря, что входной файл является выходным файлом .
gniourf_gniourf

Спасибо за исправления. Мой случай был немного другим, и я не думал о некоторых из этих ошибок применительно к этому делу.
mopo922

Вы должны поставить >> output.fileв конце вашей команды, чтобы вы никого не побуждали (включая себя) думать, что они findбудут выполняться cat {} >> output.fileдля каждого найденного файла.
gniourf_gniourf

Начиная выглядеть действительно хорошо! Одно последнее предложение: используйте -exec cat {} +вместо -exec cat {} \;, чтобы только один экземпляр catсоздавался с несколькими аргументами ( +определяется POSIX ).
gniourf_gniourf

3
Хороший ответ и предупреждающее слово - я изменил свой вариант на: find . -type f -exec cat {} + >> outputfile.txtи не мог понять, почему мой выходной файл не перестал расти на концертах, даже если каталог был всего 50 мегабайт. Это потому, что я продолжал добавлять файл outputfile.txt к себе! Поэтому просто убедитесь, что этот файл назван правильно или полностью помещен в другой каталог, чтобы избежать этого.
Thisisstackoverflow

43

если у вас есть определенный тип вывода, то сделайте что-то вроде этого

cat /path/to/files/*.txt >> finalout.txt

1
Имейте в виду, что вы теряете возможность поддерживать порядок слияния. Это может повлиять на вас, если у вас есть имена файлов, например. file_1, file_2, ... file_11, из - за естественного порядка , как сортируют файлы.
emix

16

Если все ваши файлы находятся в одном каталоге, вы можете просто сделать

cat * > 0.txt

Файлы 1.txt, 2.txt, .. перейдут в 0.txt


Уже ответил Ишвар. Имейте в виду, что вы теряете возможность поддерживать порядок слияния. Это может повлиять на вас, если у вас есть имена файлов, например. file_1, file_2, ... file_11, из - за естественного порядка , как сортируют файлы.
emix

10
for i in {1..3}; do cat "$i.txt" >> 0.txt; done

Я нашел эту страницу, потому что мне нужно было объединить 952 файла в один. Я нашел, что это работает намного лучше, если у вас много файлов. Это создаст цикл для сколь угодно большого числа чисел, и каждое из них будет следовать с помощью >> для добавления в конец 0.txt.


Вы можете использовать расширение скобки в bash, чтобы написать cat {1,2,3} .txt >> 0.txt
mcheema

9

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

cat *.log >> output.log

5

Другой вариант sed:

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

Или...

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

Или...

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

Или без перенаправления ...

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

Обратите внимание, что в последней строке также пишите merge.txt(не wmerge.txt!). Вы можете использовать, w"merge.txt"чтобы избежать путаницы с именем файла, и -nдля вывода без вывода сообщений.

Конечно, вы также можете сократить список файлов с подстановочными знаками. Например, в случае нумерованных файлов, как в приведенных выше примерах, вы можете указать диапазон в фигурных скобках следующим образом:

sed -n w"merge.txt" {1..3}.txt

4

если ваши файлы содержат заголовки и вы хотите удалить их из выходного файла, вы можете использовать:

for f in `ls *.txt`; do sed '2,$!d' $f >> 0.out; done

3

Если исходный файл содержит непечатаемые символы, они будут потеряны при использовании команды cat. Используя 'cat -v', непечатаемые символы будут преобразованы в видимые строки символов, но выходной файл все равно не будет содержать фактические непечатные символы в исходном файле. При небольшом количестве файлов альтернативой может быть открытие первого файла в редакторе (например, vim), который обрабатывает непечатаемые символы. Затем перейдите в конец файла и введите «: r second_file_name». Это будет тянуть во втором файле, включая непечатные символы. То же самое можно сделать для дополнительных файлов. Когда все файлы будут прочитаны, введите «: w». Конечным результатом является то, что первый файл теперь будет содержать то, что он делал изначально, плюс содержимое файлов, которые были прочитаны.


Это не очень хорошо для сценариев.
FKEinternet

1

Если вы хотите добавить содержимое 3 файлов в один файл, то следующая команда будет хорошим выбором:

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

Он объединит содержимое всех файлов в file4, выдавая вывод консоли /dev/null.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.