Об’єднання декількох текстових файлів в один файл в Bash


305

Який найшвидший і прагматичніший спосіб об'єднати весь * .txt файл у каталозі в один великий текстовий файл?

В даний час я використовую Windows з cygwin, тому я маю доступ до BASH.

Команда оболонки Windows також була б непоганою, але я сумніваюся, що вона є.

Відповіді:


537

Це додає вихід до all.txt

cat *.txt >> all.txt

Це перезаписує весь.txt

cat *.txt > all.txt

30
Ви можете зіткнутися з проблемою, коли вона запускає all.txt у all.txt ... У мене є проблема з grep інколи, не впевнений, що у кішки однакова поведінка.
rmeador

8
@rmeador так, це правда, якщо all.txt вже існує, у вас виникне ця проблема. Ця проблема вирішується шляхом надання вихідного файлу з іншим розширенням або переміщенням all.txt до іншої папки.
Роберт Грейнер

2
кіт * .txt >> tmp; mv tmp all.txt (і переконайтеся, що all.txt не існує заздалегідь)
Renaud

16
Я отримую "Аргумент список занадто довгий" - здогадуйтесь, він не може обробляти 40 000+ файлів.
Метт

32
Уникайте списку аргументів занадто довго, оскільки:echo *.txt | xargs cat > all.txt
5heikki

145

Пам'ятайте лише, що для всіх рішень, що надаються до цього часу, оболонка визначає порядок з'єднання файлів. Для Bash, IIRC, це алфавітний порядок. Якщо замовлення важливе, вам слід або належним чином назвати файли (01file.txt, 02file.txt тощо) або вказати кожен файл у порядку, який ви хочете, щоб він був зведений.

$ cat file1 file2 file3 file4 file5 file6 > out.txt

33

Команда оболонки Windows typeможе це зробити:

type *.txt >outputfile

typeКоманда Type також записує імена файлів в stderr, які не захоплюються >оператором переадресації (але відображатимуться на консолі).


2
Просто пам’ятайте, що якщо ви виведете файл виводу в ту саму директорію, що і вихідний файл, це спричинить дублювання, оскільки воно також поєднає новий вихідний файл двічі.
CathalMF

26

Ви можете використовувати оболонку Windows copyдля об'єднання файлів.

C:\> copy *.txt outputfile

З довідки:

Щоб додати файли, вкажіть один файл для призначення, але декілька файлів для джерела (використовуючи символи підстановки чи файл1 + файл2 + файл3).


Це, як найчистіше рішення ІМХО, в основному не має побічних ефектів, які могли б подолати початківці, на жаль, недостатньо оцінили :-(
Grmpfhmbl

ОП попросив Баша.
Великий багатий

2
Ви читали питання? "Команда оболонки Windows також була б непогана ..."
Карл Норум

8

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

for i in $(ls | grep ".txt");do cat $i >> output.txt;done

EDIT: Як сказав хтось - то в коментарях, ви можете замінити $(ls | grep ".txt")з$(ls *.txt)

EDIT: завдяки @gnourf_gnourf досвід, використання glob є правильним способом ітерації файлів у каталозі. Отже, блюзнірські вирази на зразок $(ls | grep ".txt")повинні бути замінені *.txt(див. Статтю тут ).

Гарне рішення

for i in *.txt;do cat $i >> output.txt;done

1
Чому ні for i in $(ls *.txt);do cat $i >> output.txt;done?
streamofstars

2
Обов'язкове посилання ParsingLs разом із головою (і ви заслуговуєте більше ніж один голос, бо ls | grepце дуже поганий антипатерн).
gniourf_gniourf

Отримав відгук від мене, оскільки він дозволяє проводити довільне тестування / операції за назвою файлу до виходу, і це швидко, легко і добре для практики. (У моєму випадку я хотів: для i in *; do echo -e "\ n $ i: \ n"; cat $ 1; зроблено)
Nathan Chappell

Не вдалося б ls *.txtпровалитися, якщо занадто багато файлів (список аргументів занадто довгий помилка)?
Рафаель Альмейда

6

самий прагматичний спосіб з оболонкою - це команда cat. інші способи включають,

awk '1' *.txt > all.txt
perl -ne 'print;' *.txt > all.txt

1
Це має бути правильною відповіддю для більшості обставин. Якщо будь-який текстовий файл без порожнього нового рядка, використовуючи всі вищевказані catметоди, об'єднайте останній і перший рядок із суміжних файлів.
mootmoot

6

Як щодо цього підходу?

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

Оскільки OP каже, що файли знаходяться в одному каталозі, можливо, вам потрібно буде додати -maxdepth 1до findкоманди.
codeforester

1
Прекрасно працює з великою кількістю файлів, де підхід Прийнята відповіді зазнає невдачі
амін

ах, я хотів би, щоб я знав, що означає цей плюс і подвійне переадресація ...
hello_earth

Це має бути правильна відповідь. Він буде працювати належним чином у сценарії оболонки. Ось подібний метод, якщо ви хочете сортувати вихід:sort -u --output="$OUTPUT_FILE" --files0-from=- < <(find "$DIRECTORY_NAME" -maxdepth 1 -type f -name '*.txt' -print0)
steveH

3
type [source folder]\*.[File extension] > [destination folder]\[file name].[File extension]

Наприклад:

type C:\*.txt > C:\1\all.txt

Це займе всі файли txt у папці C: \ і збереже їх у C: \ 1 Папка за назвою all.txt

Або

type [source folder]\* > [destination folder]\[file name].[File extension]

Наприклад:

type C:\* > C:\1\all.txt

Це займе всі файли, які є в папці, і помістить там Вміст у C: \ 1 \ all.txt


0

Ви можете зробити так: cat [directory_path]/**/*.[h,m] > test.txt

якщо ви використовуєте {}розширення файлів, які ви хочете знайти, виникає проблема послідовності.


0

Коли ви зіткнетеся з проблемою, коли вона вводить all.txt у all.txt, ви можете спробувати перевірити, чи існує все.txt чи ні, якщо воно існує, видалити

Подобається це:

[ -e $"all.txt" ] && rm $"all.txt"


cat *.txt > all.txt >команда перезаписує all.txt, якщо вона існує, >>додає дані в існуючий файл
Олег Бондаренко

-4

все це противно ...

ls | grep *.txt | while read file; do cat $file >> ./output.txt; done;

легкі речі.


6
Eeek! Не робіть цього. Зробитиfind . -iname "*.txt" -maxdepth 1 -exec cat {} >> out.txt \;
Chinmay Kanchi
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.