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

73

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 cate redirecionar a saída para um novo arquivo. Como uma maneira de apenas abrir dois arquivos, remover o EOFmarcador do primeiro e conectá-los - sem ter que percorrer 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 juntar arquivos grandes no Linux do que o gato?

Atualizar

Parece que caté de fato o caminho certo e a melhor maneira de ingressar em arquivos. Fico feliz em saber que eu estava usando o comando certo o tempo todo :) Obrigado a todos por seus comentários.

cwd
fonte
22
Nota lateral: Melhor não usar cat x*, porque a ordem dos arquivos depende das suas configurações de localidade. É melhor começar a digitar cat x, do que pressionar Esc e depois *- você verá a ordem expandida dos arquivos e poderá reorganizá-los.
rozcietrzewiacz
16
Em vez de cat x*você poderia considerar a expansão cinta shell, cat xa{a..g}o que amplia a seqüência especificada para cat Xaa xab XAC xad Xae XAF XAG
Peter.O
3
@rozcietrzewiacz - você pode dar um exemplo de como eu ajustaria minha configuração de local que quebraria cat x*? Será que a nova definição de local não afectam também splitpara que, se splite cat x*foram usados no mesmo sistema que sempre funciona?
Cwd
3
"abrir dois arquivos, remover o marcador EOF do primeiro e conectá-los - sem ter que percorrer todo o conteúdo." ... parece que você precisa inventar um novo sistema de arquivos para fazer o que deseja
JoelFan
6
@cwd: Olhando split.cem GNU Coreutils, os sufixos são construídos a partir de uma matriz fixa de caracteres: static char const *suffix_alphabet = "abcdefghijklmnopqrstuvwxyz";. O sufixo não seria afetado pelo código do idioma. (Mas eu não acho que qualquer local sã iria reorganizar as letras minúsculas, mesmo EBCDIC mantém sua ordem standard.)
Keith Thompson

Respostas:

50

Isso é exatamente o que catfoi feito. 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 é um canal - apenas redireciona a saída.

rozcietrzewiacz
fonte
O cat x, then press Esctruque que você mencionou é puro .. Eu estive procurando por algo assim, graças ... bom comentário e boa resposta
Peter.O
2
De nada :) Além disso, quando você tiver essa lista de arquivos na linha de comando, poderá Ctrl+Wrecortar uma palavra e Ctrl+Ycolá-la.
rozcietrzewiacz
gato significa "concatenar"
JoelFan 15/11
4
.. e "catenar" deriva de uma palavra latina "catena" que significa "uma corrente" .. concatenar é unir os elos de uma corrente. ... (e um pouco mais off-topic, uma curva catenária também derrives de "catena" É a forma como uma cadeia trava.)
Peter.O
19

Sob o capô

Não há maneira mais eficiente do que copiar o primeiro arquivo, depois copiar o segundo arquivo e assim por diante. Tanto o DOS copyquanto o catfazem.

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. Como a maioria dos arquivos não possui um número inteiro de blocos, 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 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.

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

splite catsão maneiras simples de dividir e juntar arquivos. splitcuida da produção de arquivos nomeados em ordem alfabética, para que cat *funcione para ingressar.

Uma desvantagem da catjunção é que ela não é robusta contra os modos de falha comuns. Se um dos arquivos estiver truncado ou ausente, catnão reclamará, você terá apenas uma saída danificada.

Existem utilitários de compactação que produzem arquivos com várias partes, como zipsplite rar -v. Eles não são muito unixy, porque compactam e empacotam (montam vários arquivos em um) além de dividir (além disso, descompactam e descompactam além de se unirem). Mas eles são úteis, pois verificam se você possui todas as partes e se estão completas.

Gilles
fonte
8

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

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

Ignacio Vazquez-Abrams
fonte
Eu estava imaginando usando cat para exibir vários gigabytes de código no console e depois capturá-lo e colocá-lo em um arquivo. Essa é a imagem mental que tenho para o que deve estar acontecendo quando uso cat e redireciono a saída que não consigo ver. Parecia que havia uma maneira de abrir dois arquivos, conectá-los e fechá-los. Seria mais eficiente do que executar todas as linhas de código cat. Obrigado por me informar sobre a conexão direta.
Cwd
@cwd Seria possível criar um sistema de arquivos no qual você pudesse juntar dois arquivos dessa maneira, mas isso complicaria imensamente o design do sistema de arquivos. Você otimizaria essa operação com o custo de tornar muitas tarefas comuns mais complicadas e lentas.
Gilles
@ Gilles - seria interessante saber mais sobre os detalhes de baixo nível. Para mim, ler todos os setores do disco rígido para vários arquivos e depois despejá-los em outros setores não utilizados no disco parece ineficiente. E acho que os arquivos grandes precisam ser armazenados em vários blocos de setores livres às vezes, porque nem sempre existem blocos suficientes lado a lado para armazená-los. Portanto, teoricamente, você pode juntar arquivos em um, removendo o marcador EOF e apontando para o grupo de setores no início do próximo arquivo. * nix é poderoso, então eu me perguntei se havia uma maneira melhor do que o gato.
Cwd
@cwd Não há "marcador EOF". Nenhum sistema de arquivos moderno e saudável funciona assim, porque impede que alguns caracteres ocorram nos arquivos (ou então requer codificações complexas). Mas mesmo se houvesse um marcador EOF, na maioria das vezes, você não teria o arquivo correto após ele.
Gilles
Eu quis dizer o conceito do marcador EOF e não um marcador EOF real. Caso contrário, se você observar os bits e bytes de um arquivo no disco rígido, como saberá onde ele termina? Você especifica o tamanho do arquivo no início? Estou falando de uma coisa realmente de baixo nível. É a isso que você também está se referindo?
Cwd
3

Uma 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 outro lugar, é possível.

Se necessário, eu posso fornecer a fonte.

glglgl
fonte
0

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, obviamente, myImage.isoseja um arquivo especial (pipe nomeado) e não um arquivo regular, isso pode ser útil ou não, dependendo do que você está tentando fazer.

golimar
fonte
0

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 pelo 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 da Divisão por 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 nos arquivos, os arquivos pequenos não devem ser danificados. Todos os arquivos pequenos (parte) também devem estar no mesmo diretório.

Nole
fonte