Як об'єднати всі (текстові) файли в каталозі в один?


89

У мене 14 файлів, які є частинами одного тексту. Я хотів би об'єднати їх в одне ціле. Як це зробити?

Відповіді:


168

Це технічно те, що cat("конкатенат") повинен робити, хоча більшість людей просто використовують його для виведення файлів у stdout. Якщо ви дасте йому кілька імен файлів, вони видадуть їх усі послідовно, а потім ви можете перенаправити це в новий файл; у випадку, якщо всі файли просто використовуйте *(або /path/to/directory/*якщо ви вже не в каталозі), і ваша оболонка розширить її до всіх імен файлів

$ cat * > merged-file

15
Будьте уважні, що ваша котирувана команда, ймовірно, буде робити лише те, що хоче плакат, якщо вони пронумеровані таким чином, щоб оболонка розширювалася *в "природному" порядку. Якщо у вас "file1.txt ... file9.txt ... file14.txt", він не працюватиме, оскільки file1? .Txt буде сортувати між file1.txt та file2.txt. Вам доведеться перейменувати їх у "file01.txt ... file09.txt ... file14.txt". Скажіть, echo *якщо ви не впевнені.
Warren Young

2
@Warren: хороший момент (або ви можете використовувати zsh і встановити його numeric_glob_sortпараметр).
Жиль

2
@ warren-young правильний, корисний коментар із попередженням. Але в моєму фактичному порядку порядок не має ніякої різниці (тому що файли містять просто прості оператори SQL, які вставляють записи даних, які не мають залежностей).
Іван

2
Остерігайтеся, якщо кількість файлів перевищує певний ліміт, ви можете працювати з помилками на кшталт - / bin / cat: Аргумент надто довгий
Nupur

1
@ ARA1307 Тільки якщо файл вже існує; інакше глобус буде розширений до того, як оболонка відкриє файл для запису на нього. Хороший момент у цій ситуації, проте
Майкл Мрозек

25

Якщо ваші файли не в одному каталозі, ви можете використовувати команду find перед конкатенацією:

find /path/to/directory/ -name *.csv -print0 | xargs -0 -I file cat file > merged.file

Дуже корисно, коли ваші файли вже замовлені, і ви хочете об'єднати їх, щоб проаналізувати їх.


Більш портативно:

find /path/to/directory/ -name *.csv -exec cat {} + > merged.file

Це може або не може зберегти порядок файлів.


1
Це шлях, якщо у вас багато файлів. Ви уникаєте помилки "список аргументів занадто довгий".
Маті Тернер

2
Вам потрібно -name "* .csv" замість -name * .csv - без лапок воно не виходить.
Петріс

Потреба в котируваннях залежить від версії команди find, особливо в пошуку і аварії це проблема, коли ви перебуваєте на Mac, версії обох програм трохи застаріли. Поки що на ubuntu, fedora, debian та CentOS він працював без проблем, без лапок
3nrique0

Я очікував би котирувальну версію працювати , коли немає файлів в поточному каталозі , відповідних шаблон "*.csv", так як оболонка буде потім передати буквальний *в find.
RJHunter


9

Команда

$ cat * > merged-file

насправді є небажаний побічний ефект від включення "об'єднаного файлу" в конкатенацію, створюючи файл, що вибігає. Щоб обійти це, напишіть об'єднаний файл в інший каталог;

$ cat * > ../merged-file

або використовувати відповідність шаблону, яка буде ігнорувати об'єднаний файл;

$ cat *.txt > merged-file

14
cat * > merged-fileпрацює чудово. Глобуси обробляються до створення файлу. Якщо вона merged-fileвже існує, cat(щонайменше , моя) виявить, що це вихідний файл, і відмовиться його читати. Якщо файл вже існує І ви перенаправляєте пізніше на конвеєрі, то, очевидно, це зробити не можна, тож тоді і лише тоді ви отримуєте утікаючий файл.
Кевін

catне має можливості визначити, чи файл є вихідним. Перенаправлення відбувається в оболонці; catтільки відбитки на stdout.
bfontaine

8

Як і інші звідси кажуть ... Можна використовувати cat

Скажімо, у вас є:

~/file01
~/file02
~/file03
~/file04
~/fileA
~/fileB
~/fileC
~/fileD

І ви хочете лише file01до file03і fileAдо fileC:

cat ~/file01 ~/file02 ~/file03 ~/fileA ~/fileB ~/fileC > merged-file

Або, використовуючи розширення дужок:

cat ~/file0{1..3} ~/file{A..C} > merged-file

Або, використовуючи шикарні розширення дужок:

cat ~/file{0{1..3},{A..C}} > merged-file

Або ви можете використовувати forцикл:

for i in file0{1..3} file{A..C}; do cat ~/"$i"; done > merged-file

1
Зауважте, що рядок [01-03]не працюватиме як глобальний шаблон.
Kusalananda


0

Ще один варіант - 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
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.