Как объединить все (текстовые) файлы в каталоге в один?

89

У меня есть 14 файлов, которые являются частью одного текста. Я хотел бы объединить их в один. Как это сделать?

Иван
источник

Ответы:

169

Технически это то, что cat(«сцепление») должно делать, хотя большинство людей просто используют его для вывода файлов на стандартный вывод. Если вы дадите ему несколько имен файлов, он выведет их все последовательно, а затем вы сможете перенаправить их в новый файл; в случае всех файлов просто используйте *(или /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 *если ты не уверен.
Уоррен Янг
2
@Warren: хороший момент (или вы можете использовать zsh и установить его numeric_glob_sortопцию).
Жиль
2
@ Уоррен-молодой правильный, полезный предупреждающий комментарий. Но в моем случае порядок не имеет значения (поскольку файлы содержат просто простые операторы 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

Это может или не может сохранить порядок файлов.

3nrique0
источник
1
Это путь, если у вас много файлов. Вы избегаете ошибки «список аргументов слишком длинный».
Мати Тернер
2
Вам нужно -name "* .csv" вместо -name * .csv - без кавычек это не сработает.
Петерис
Потребность в кавычках зависит от версии команды find, особенно в find и awk. Это проблема, когда вы работаете на 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только печатает на стандартный вывод.
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]не будет работать в качестве шаблона сглаживания.
Кусалананда
0

Вы можете указать patternфайл, а затем объединить их все следующим образом:

cat *pattern* >> mergedfile
user182845
источник
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
харини
источник