Como você pode concatenar duas enormes arquivos com muito pouco espaço em disco livre? [fechadas]

StackOverflow https://stackoverflow.com/questions/290700

Pergunta

Suponha que você tem dois arquivos enormes (vários GB) que deseja concatenar juntos, mas que você tem espaço em disco muito pouco de reposição (digamos que um par cem MB). Isto é, dado file1 e file2, você quer acabar com um único arquivo que é o resultado da concatenação file1 e juntos file2 byte a byte, e excluir os arquivos originais.

Você não pode fazer o cat file2 >> file1; rm file2 óbvia, uma vez que entre as duas operações, você iria ficar sem espaço em disco.

Soluções em qualquer e todas as plataformas com ferramentas livres ou não-livres são bem-vindos; este é um problema hipotético eu pensei enquanto eu estava baixando um ISO Linux no outro dia, e o download tem parcialmente interrompida através devido a um soluço sem fio.

Foi útil?

Solução

Eu acho que a dificuldade é determinar como o espaço pode ser recuperado a partir dos arquivos originais.

Eu acho que o trabalho seguinte poder:

  1. Alocar um arquivo esparso do tamanho combinado.
  2. Copiar 100Mb a partir do final do segundo arquivo para o final do novo arquivo.
  3. truncar 100Mb do final do segundo arquivo
  4. Curva 2 e 3 até que você terminar o segundo arquivo (com 2. modificado para o local correto no arquivo de destino).
  5. Do 2 & 3 & 4, mas com o primeiro arquivo.

Isso tudo depende de suporte no arquivo esparso, e arquivo de truncagem liberando espaço imediatamente.

Se você realmente queria fazer isso, então você deve investigar o comando dd. que pode fazer a etapa de copiar

Alguém em outra resposta deu uma solução elegante que não requer arquivos esparsos, mas faz cópia arquivo2 duas vezes:

  1. Copiar 100Mb pedaços a partir do final do arquivo 2 para um novo arquivo 3, terminando em ordem inversa. Truncar arquivo 2 que você vá.
  2. pedaços de cópia de 100 Mb a partir do final de arquivo 3 em arquivo 1, terminando com os pedaços em sua ordem original, no final do arquivo 1. Truncando arquivo 3 como você vai.

Outras dicas

tempo gasto descobrir solução inteligente envolvendo baralhar-setor do disco e manipulação de cadeia arquivo: 2-4 horas

tempo gasto adquirindo / escrever software para fazer no local de cópia e truncate: 2-20 horas

tempos medianos US $ 50 / hr taxa de programador: $ 400- $ 1200

custo do drive USB 1TB: $ 100- $ 200

capacidade de entender a frase "custo de oportunidade": não tem preço

Aqui está uma ligeira melhoria em relação a minha primeira resposta .

Se você tem 100MB livre, copie o último 100MB a partir do segundo arquivo e criar um terceiro arquivo. Truncar o segundo arquivo assim que é agora 100MB menor. Repita esse processo até o segundo arquivo foi completamente decomposto em pedaços 100MB individuais.

Agora, cada um desses arquivos 100MB pode ser acrescentado ao primeiro arquivo, um de cada vez.

Com essas restrições eu espero que você precisa para mexer com o sistema de arquivos; editar diretamente o tamanho e alocação de blocos de arquivos.

Em outras palavras, esqueça baralhar quaisquer blocos de conteúdo de arquivos ao redor, apenas editar as informações sobre esses arquivos.

Se o arquivo é altamente compressível (ou seja, logs.):

gzip file1

gzip file2

zcat file1 file2 | gzip > file3

rm file1

rm file2

gunzip file3

Correndo o risco de soar leviano, que considerou ter a opção de ficar apenas um disco maior? Provavelmente seria mais rápido ...

Não é muito eficiente, mas acho que isso pode ser feito.

Abrir o primeiro arquivo em modo de adição, e copiar blocos do segundo arquivo a ele até que o disco está quase cheio. Para o restante do segundo arquivo, copiar blocos a partir do ponto em que parou de volta para o início do arquivo via de acesso aleatório de E / S. Truncar o arquivo depois de ter copiado o último bloco. Repita até terminar.

Obviamente, a resposta econômica é comprar mais armazenamento assumindo que é uma resposta possível. Pode não ser, embora - sistema integrado com nenhuma maneira de anexar mais espaço de armazenamento, ou mesmo nenhum acesso ao equipamento em si -. Digamos, sonda espacial em vôo

A resposta anteriormente apresentadas com base no sistema de arquivo esparso é bom (que não seja a natureza destrutiva do que se algo der! Errado) se você tiver um sistema de arquivo esparso. E se você não fizer isso, embora?

A partir do final do arquivo 2 blocos de texto para o início do arquivo de destino revertê-las como você vai. Depois de cada bloco que você truncar o arquivo de origem para o comprimento não copiados. Repita para o arquivo # 1.

Neste ponto, o arquivo de destino contém todos os dados para trás, os arquivos de origem já se foram.

Leia uma quadra da torta e do final do arquivo alvo, invertê-los e gravá-los para o local o outro veio. Trabalhar o seu caminho para dentro lançando blocos.

Quando você é feito o arquivo de destino é a concatenação dos arquivos de origem. Nenhum sistema de arquivo esparso necessário, sem mexer com o sistema de arquivos necessários. Isto pode ser realizado em zero bytes livre como os dados podem ser mantidos na memória.

ok, para o entretenimento teórica, e somente se você prometer que não vai desperdiçar seu tempo realmente fazê-lo:

  • arquivos são armazenados no disco em pedaços
  • as peças estão ligadas em uma cadeia

Assim, você pode concatenar os arquivos por:

  • ligando a última peça do primeiro arquivo para a primeira parte do último arquivo
  • alterando a entrada de diretório para o primeiro arquivo para mudar a última peça e tamanho de arquivo
  • remover a entrada de diretório para o último arquivo
  • limpeza marca de fim-de-arquivo do primeiro arquivo, se houver
  • nota que se o último segmento do primeiro arquivo só é parcialmente preenchido, você terá que copiar dados "para cima" os segmentos do último arquivo para evitar ter de lixo no meio do arquivo [graças @Wedge!]

Este seria otimamente eficiente:. Alterações mínimas, cópia mínimo, não há espaço em disco livre necessário

Agora vá comprar um drive USB; -)

Dois pensamentos:

Se você tem RAM física suficiente, você pode realmente ler o segundo arquivo inteiramente na memória, exclua-o, em seguida, escrevê-lo em modo de acréscimo para o primeiro arquivo. Claro, se você poder perder após a exclusão, mas antes de completar a gravação, você tem parte perdida do segundo arquivo para o bem.

Temporariamente reduzir o espaço em disco usado por funcionalidade OS (memória por exemplo virtual, "Lixeira" ou similar). Provavelmente, só de utilização no Windows.

Eu duvido que esta é uma resposta direta à pergunta. Você pode considerar isso como uma forma alternativa para resolver o problema.

Eu acho que é possível considerar 2º arquivo como a parte 2 do primeiro arquivo. Normalmente em zip aplicação, veríamos um enorme arquivo é dividido em várias partes. Se você abrir a primeira parte, o pedido seria automaticamente considerar as outras partes no processamento posterior.

Podemos simular a mesma coisa aqui. Como @edg apontou, mexer sistema de arquivos seria uma maneira.

você poderia fazer isso:

head file2 --bytes=1024 >> file1 && tail --bytes=+1024 file2 >file2 

Você pode aumentar a 1024 de acordo com a quantidade de espaço em disco extra que você tem, em seguida, basta repetir isto até que todos os bytes foram transferidos.

Esta é provavelmente a maneira mais rápida de fazê-lo (em termos de tempo de desenvolvimento)

Você pode ser capaz de ganhar espaço através da compressão de todo o sistema de arquivos. Acredito NTFS suporta isso, e estou certo de que há sabores de sistemas de arquivos * nix que o suportam. Ele também teria a vantagem de depois de copiar os arquivos que você ainda teria mais espaço livre em disco do que quando você começou.

OK, mudando o problema um pouco. As chances são de que há outras coisas no disco que você não precisa, mas você não sabe o que é ou onde está. Se você pudesse encontrá-lo, você pode excluí-lo, e então talvez você teria espaço extra suficiente.

Para encontrar estes "tumores", se alguns grandes, ou lotes de pequenos, eu uso um pequeno programa de amostragem. A partir do topo de um diretório (ou o root) faz duas passagens. Na passagem 1, ele anda a árvore de diretórios, somando os tamanhos de todos os arquivos para obter um total de N bytes. Em passe de 2,-lo novamente anda a árvore de diretórios, fingindo que está a ler todos os arquivos. Toda vez que ele passa N / 20 bytes, ela mostra o caminho do diretório e nome do arquivo é "leitura". Assim, o resultado final é 20 amostras profundas de nomes de caminho uniformemente distribuídos por todos os bytes no diretório.

Em seguida, basta olhar para essa lista de coisas que aparece muita coisa que você não precisa, e ir soprar-la.

(é o espaço equivalente do método de amostragem que eu uso para otimização de desempenho.)

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top