Como mesclar todos os arquivos (texto) em um diretório em um?

89

Eu tenho 14 arquivos todos sendo partes de um texto. Eu gostaria de fundi-los em um. Como fazer isso?

Ivan
fonte

Respostas:

168

Tecnicamente, é isso que cat("concatenar") deve fazer, mesmo que a maioria das pessoas o use para gerar arquivos no stdout. Se você fornecer vários nomes de arquivos, todos eles serão exibidos sequencialmente e poderá redirecioná-los para um novo arquivo; no caso de todos os arquivos, basta usar *(ou /path/to/directory/*se você ainda não estiver no diretório) e seu shell o expandirá para todos os nomes de arquivo

$ cat * > merged-file
Michael Mrozek
fonte
15
Lembre-se de que seu comando citado provavelmente fará apenas o que o pôster deseja se estiver numerado de forma que o shell se expanda *na ordem "natural". Se você tiver "arquivo1.txt ... arquivo9.txt ... arquivo14.txt", ele não funcionará porque arquivo1? .Txt será classificado entre arquivo1.txt e arquivo2.txt. Você teria que renomeá-los para "file01.txt ... file09.txt ... file14.txt". Diga echo *se você não tem certeza.
Warren Young
2
@ Warren: bom ponto (ou você pode usar o zsh e definir sua numeric_glob_sortopção).
Gilles
2
@ warren-young, um comentário de aviso correto e útil. Mas, no meu caso real, a ordem não faz diferença (porque os arquivos contêm apenas instruções SQL simples, inserindo registros de dados que não têm dependências).
Ivan
2
Cuidado, se a contagem de arquivos excede um certo limite, você pode executar em erros como - / bin cat /: lista de argumentos muito longa
Nupur
1
@ ARA1307 Apenas se o arquivo já existir; caso contrário, o globo será expandido antes que o shell abra o arquivo para gravar nele. Bom ponto nessa situação, porém
Michael Mrozek
25

Se seus arquivos não estiverem no mesmo diretório, você poderá usar o comando find antes da concatenação:

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

Muito útil quando seus arquivos já foram solicitados e você deseja mesclá-los para analisá-los.


Mais portatilmente:

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

Isso pode ou não preservar a ordem dos arquivos.

3nrique0
fonte
1
Este é o caminho a percorrer se você tiver muitos arquivos. Você evita um erro "lista de argumentos muito longa".
Мати Тернер
2
Você precisa de -name "* .csv" em vez de -name * .csv - sem as aspas, ele falha.
Peteris
A necessidade de cotações depende da versão do comando find, especialmente em find e awk; é um problema quando você está em um mac; as versões dos dois programas são um pouco antigas. Até agora no Ubuntu, Fedora, Debian e CentOS funcionou sem problemas, sem as aspas
3nrique0
Eu esperaria que a versão não citada funcionasse quando não houver arquivos no diretório atual que correspondam ao padrão "*.csv", pois o shell passaria o literal *para find.
RJHunter
9

O comando

$ cat * > merged-file

na verdade, tem o efeito colateral indesejado de incluir 'arquivo mesclado' na concatenação, criando um arquivo em fuga. Para contornar isso, escreva o arquivo mesclado em um diretório diferente;

$ cat * > ../merged-file

ou use uma correspondência de padrão que ignorará o arquivo mesclado;

$ cat *.txt > merged-file
Christopher Jones
fonte
14
cat * > merged-filefunciona bem. Os globos são processados ​​antes da criação do arquivo. Se merged-filejá existir, cat(pelo menos o meu) detectará que é o arquivo de saída e se recusará a lê-lo. Se o arquivo já existir E você tiver o redirecionamento posteriormente no pipeline, obviamente ele não poderá fazer isso; então, e somente então, você obterá o arquivo descontrolado.
21412 Kevin
catnão tem como detectar se o arquivo é o de saída. O redirecionamento acontece no shell; catsomente imprime em stdout.
precisa saber é o seguinte
8

Como os outros daqui dizem ... Você pode usar cat

Vamos dizer que você tem:

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

E você deseja apenas file01para file03e fileApara fileC:

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

Ou, usando expansão de chave:

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

Ou, usando a expansão de braçadeira mais sofisticada:

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

Ou você pode usar o forloop:

for i in file0{1..3} file{A..C}; do cat ~/"$i"; done > merged-file
Florin Idita
fonte
1
Observe que a corda [01-03]não funcionará como um padrão brilhante.
Kusalananda
0

Você pode especificar o patternarquivo e mesclar todos eles da seguinte maneira:

cat *pattern* >> mergedfile
user182845
fonte
0

Outra opção é sed:

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

Ou...

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

Ou...

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

Ou sem redirecionamento ...

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

Observe que a última linha também grava merge.txt (não wmerge.txt!). Você pode usar w "merge.txt" para evitar confusão com o nome do arquivo e -n para saída silenciosa.

Obviamente, você também pode reduzir a lista de arquivos com caracteres curinga. Por exemplo, no caso de arquivos numerados, como nos exemplos acima, você pode especificar o intervalo com chaves desta maneira:

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