desenv-web-rp.com

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

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

split -b 100m myImage.iso

Isso geralmente me dá algo como

xaa
xab
xac
xad

E para reuni-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 possui um comando de cópia para arquivos binários. A ajuda menciona que este comando foi projetado para poder combinar vários arquivos. Funciona com esta sintaxe: (/b é para o modo binário)

copy /b file1 + file2 + file3 outputfile

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

Atualização

Parece que cat é de fato 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 por seus comentários.

79
cwd

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

54
rozcietrzewiacz

Sob o capô

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

Cada arquivo é armazenado independentemente de outros arquivos no disco. Quase todo sistema de arquivos projetado para armazenar dados em um dispositivo semelhante a um disco opera 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 possui um número inteiro de blocos, portanto o último bloco é apenas 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 os "blocos 46798 a 47913" em vez de "bloco 46798, bloco 46799, ...". Quando o sistema operacional precisa criar um novo arquivo, ele procura por blocos gratuitos. Os blocos não precisam ser consecutivos: se apenas os blocos 4, 5, 98 e 178 forem gratuitos, você ainda poderá armazenar um arquivo de 4kB. O uso de blocos, em vez de descer para o nível de bytes, ajuda a encontrar blocos livres para um arquivo novo ou crescente consideravelmente mais rápido e reduz os problemas devido à fragmentação ao criar ou aumentar e excluir ou reduzir muitos arquivos (deixando um número crescente de buracos).

Você poderia suportar blocos parciais no meio do arquivo, mas isso acrescentaria uma complexidade considerável, principalmente ao acessar arquivos de forma não sequencial: para pular para o 10340º byte, não era possível pular para o 100º byte do 11º bloco, você teria para verificar o comprimento de cada bloco intermediário.

Dado o uso de blocos, você não pode unir apenas dois arquivos, porque, em geral, o primeiro arquivo termina no meio do bloco. Claro, você pode ter um caso especial, mas apenas se desejar excluir os dois arquivos ao concatenar. Isso seria um tratamento altamente específico para uma operação rara. Esse tratamento especial não funciona por si só, porque em um sistema de arquivos típico, muitos arquivos estão sendo acessados ​​ao mesmo tempo. Portanto, se você deseja 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 tenta concatenar A e B enquanto alguém concatena A e C? E assim por diante. Em suma, essa rara otimização seria um fardo enorme.

Em suma, você não pode tornar os arquivos de junção mais eficientes sem fazer grandes sacrifícios em outros lugares. Não vale a pena.

Sobre a divisão e união

split e cat são maneiras simples de dividir e unir arquivos. split cuida da produção de arquivos nomeados em ordem alfabética, para que cat * trabalha para ingressar.

Uma desvantagem de cat para a união é que ela não é robusta contra os modos de falha comuns. Se um dos arquivos estiver truncado ou ausente, cat não irá reclamar, você 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, descompactam e descompactam além de se unir). Mas eles são úteis, pois verificam se você possui todas as partes e se estão completas.

19

Parece que deve haver uma maneira mais eficiente do que canalizar todo o conteúdo pelos stdin/stdout do sistema

Só que não é exatamente isso que está acontecendo. O Shell está conectando o stdout de catdiretamente ao arquivo aberto, o que significa que "passar pelo stdout" é o mesmo que gravar no disco.

8
Ignacio Vazquez-Abrams

Certa vez, tive exatamente esse problema: queria ingressar em alguns arquivos, mas não tinha espaço em disco suficiente para mantê-los duplamente.

Então eu escrevi vários programas:

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

Isso me permitiu fazer algo como

partto sourcefile | mybuffer 128M >>cumufile

e, portanto, removendo o arquivo de origem enquanto 128M ainda não estava gravado. Um pouco perigoso, mas se os dados não forem tão preciosos ou também existirem em algum outro lugar, é possível.

Se necessário, eu posso fornecer a fonte.

3
glglgl

Divisão de arquivos

Dividir por tamanho

Se você deseja dividir arquivos grandes em arquivos pequenos e escolher o nome e o tamanho dos arquivos de saída pequenos, é esse o caminho.

split -b 500M videos\BigVideoFile.avi SmallFile.

Dessa maneira, você escolhe dividir um arquivo grande em partes menores de 500 MB. Você também deseja que os nomes dos arquivos de peça sejam SmallFile. Observe que você precisa de um ponto após o nome do arquivo. O resultado deve ser a geração de novos arquivos como este:

SmallFile.ab SmallFile.ad SmallFile.af SmallFile.ah SmallFile.aj
SmallFile.aa SmallFile.ac SmallFile.ae SmallFile.ag SmallFile.ai SmallFile.ak
...

Dividir por número de linhas

Dessa forma, você dividirá o arquivo de texto em arquivos menores limitados a 50 linhas.

split -l 50 text_to_split.txt

O resultado deve ser algo como isto:

xaa xab xac ...

Dividir por bytes

Divida em arquivos pequenos com tamanho personalizado de arquivos pequenos em bytes:

split -b 2048 BigFile.mp4

O resultado deve ser semelhante ao resultado de Divisão pelo número de linhas .

arquivos ingressando

Você pode juntar arquivos de duas maneiras. O primeiro é:

cat SmallFile.* > OutputBigVideoFile.avi

ou com:

cat SmallFile.?? > OutputBigVideoFile.avi

Nota: Ao ingressar em um arquivo, os arquivos pequenos não devem ser danificados. Todos os arquivos pequenos (parte) também devem estar no mesmo diretório.

1
Nole

Tecnicamente falando, essa é uma maneira de acessar o arquivo inteiro sem precisar ler e gravar 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 então use myImage.iso, por exemplo

$ md5sum myImage.iso

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

0
golimar