Qual é a melhor maneira de juntar arquivos novamente depois de dividi-los?

67

Se eu tiver um arquivo grande e precisar dividi-lo em blocos de 100 megabytes, farei

split -b 100m myImage.iso

Isso geralmente me dá algo como

xaa
xab
xac
xad

E para recuperá-los, tenho usado

cat x* > myImage.iso

Parece que deve haver uma maneira mais eficiente do que ler cada linha de código em um grupo de arquivos com cat e redirecionar a saída para um novo arquivo. Como uma maneira de abrir dois arquivos, remover o marcador EOF do primeiro e conectá-los - sem ter que passar por todo o conteúdo.

O Windows / DOS tem um comando de cópia para arquivos binários. A ajuda menciona que esse comando foi projetado para ser capaz de combinar vários arquivos. Funciona com esta sintaxe: ( /b é para modo binário)

copy /b file1 + file2 + file3 outputfile

Existe algo semelhante ou uma maneira melhor de juntar arquivos grandes no Linux do que o gato?

Atualizar

Parece que cat é, na verdade, o caminho certo e a melhor maneira de juntar arquivos. Fico feliz em saber que eu estava usando o comando certo o tempo todo :) Obrigado a todos pelo seu feedback.

    
por cwd 15.11.2011 / 13:17

5 respostas

45

Isso é exatamente o que cat foi criado. Como é uma das ferramentas GNU mais antigas, acho muito improvável que qualquer outra ferramenta faça isso mais rápido / melhor. E não é piping - está apenas redirecionando a saída.

    
por 15.11.2011 / 13:24
18

Sob o capô

Não há maneira mais eficiente do que copiar o primeiro arquivo, depois copiar o segundo arquivo depois dele e assim por diante. Ambos DOS copy e cat fazem isso.

Cada arquivo é armazenado independentemente de outros arquivos no disco. Quase todos os sistemas de arquivos projetados para armazenar dados em um dispositivo parecido com um disco operam por blocos. Aqui está uma apresentação altamente simplificada do que acontece: o disco é dividido em blocos de, digamos, 1kB, e para cada arquivo, o sistema operacional armazena a lista de blocos que o compõem. A maioria dos arquivos não é um número inteiro de blocos, então o último bloco está parcialmente ocupado. Na prática, os sistemas de arquivos têm muitas otimizações, como compartilhar o último bloco parcial entre vários arquivos ou armazenar “blocos 46798 a 47913” em vez de “bloco 46798, bloco 46799,…”. Quando o sistema operacional precisa criar um novo arquivo, ele procura blocos livres. Os blocos não precisam ser consecutivos: se apenas os blocos 4, 5, 98 e 178 estiverem livres, você ainda poderá armazenar um arquivo de 4kB. Usar blocos em vez de descer para o nível de byte ajuda a encontrar blocos livres para um arquivo novo ou em crescimento consideravelmente mais rápido e reduz os problemas devido à fragmentação quando você cria ou amplia e apaga ou reduz muitos arquivos (deixando um número crescente de furos).

Você poderia suportar blocos parciais no arquivo intermediário, mas isso acrescentaria uma complexidade considerável, particularmente ao acessar arquivos de forma não sequencial: para ir para o byte 10340th, você não podia mais pular para o 100º byte do 11º bloco, teria que verificar o comprimento de cada bloco interveniente.

Dado o uso de blocos, você não pode simplesmente juntar dois arquivos, porque em geral o primeiro arquivo termina no meio do bloco. Claro, você poderia ter um caso especial, mas apenas se você quiser excluir os dois arquivos ao concatenar. Isso seria um tratamento altamente específico para uma operação rara. Esse tratamento especial não vive sozinho, porque em um sistema de arquivos típico, muitos arquivos estão sendo acessados ao mesmo tempo. Então, se você quiser adicionar uma otimização, precisa pensar com cuidado: o que acontece se algum outro processo estiver lendo um dos arquivos envolvidos? O que acontece se alguém tentar concatenar A e B enquanto alguém está concatenando A e C? E assim por diante. Tudo somado, essa otimização rara seria um fardo enorme.

Em resumo, você não pode tornar os arquivos de entrada mais eficientes sem fazer grandes sacrifícios em outro lugar. Não vale a pena.

Ao dividir e entrar

split e cat são formas simples de dividir e unir arquivos. split cuida de produzir arquivos nomeados em ordem alfabética, para que cat * trabalhe para ingressar.

Uma desvantagem de cat para junção é que ela não é robusta em relação aos modos de falha comuns. Se um dos arquivos estiver truncado ou faltando, cat não irá reclamar, você só terá uma saída danificada.

Existem utilitários de compactação que produzem arquivos com várias partes, como zipsplit e rar -v . Eles não são muito unixy, porque compactam e empacotam (montam vários arquivos em um) além de dividir (e, ao contrário, descompactar e descompactar além de unir). Mas são úteis porque verificam se você tem todas as partes e se as partes estão completas.

    
por 16.11.2011 / 01:12
8

Seems like there should be a more efficient way than piping all of the contents through the system's stdin / stdout

Exceto que não é realmente o que está acontecendo. O shell está conectando o stdout de cat diretamente ao arquivo aberto, o que significa que "passar por stdout" é o mesmo que gravar em disco.

    
por 15.11.2011 / 13:26
3

Eu já tive exatamente esse problema: queria juntar alguns arquivos, mas não tinha espaço suficiente em disco para mantê-los duplamente.

Então eu escrevi vários programas:

  • um para "sugar" um arquivo lendo-o, enviando-o para stdout e, se terminar, removendo-o
  • e um para armazenar dados "on the fly".

Isso me permitiu fazer algo parecido com

partto sourcefile | mybuffer 128M >>cumufile

e, assim, removendo o arquivo de origem enquanto 128M ainda não foi escrito. Um pouco perigoso, mas se os dados não são tão preciosos, ou eles existem em outro lugar também, é viável.

Se necessário, posso fornecer a fonte.

    
por 16.11.2011 / 01:05
0

Tecnicamente falando, esta é uma maneira de acessar o arquivo inteiro sem ter que ler e escrever todo o conteúdo, e pode ser útil para arquivos grandes ou se houver pouco espaço:

$ mkfifo myImage.iso
$ cat xa{a..g} > myImage.iso &

E, em seguida, use myImage.iso , por exemplo

$ md5sum myImage.iso

Embora, é claro, myImage.iso seja um arquivo especial (named pipe) e não um arquivo regular, então isso pode ser útil ou não, dependendo do que você está tentando fazer.

    
por 19.01.2017 / 15:21