Dividir arquivos usando tar, gz, zip ou bzip2 [fechado]

144

Preciso compactar um arquivo grande de cerca de 17 a 20 GB. Eu preciso dividi-lo em vários arquivos de cerca de 1 GB por arquivo.

Procurei uma solução via Google e encontrei maneiras de usar splite catcomandos. Mas eles não funcionaram para arquivos grandes. Além disso, eles não funcionarão no Windows; Eu preciso extraí-lo em uma máquina Windows.

Aka
fonte
3
Sinto sua dor, mas isso não parece estar relacionado à programação.
Jason S
1
Muitos programas de compactação (por exemplo, o 7-Zip) podem dividir o arquivo compactado em volumes de um tamanho especificado para facilitar a distribuição.
1013 Martin Liversage
Isso pertence ao superuser.com, mas a versão beta privada não começa até amanhã, disseram-me.
JesperE
Posso perguntar por que você precisa desse arquivo compactado?
Jan Jungnickel
Se uma das duas soluções viáveis ​​postadas aqui não der certo, ele precisará de uma solução de programação.
Joshua

Respostas:

253

Você pode usar o splitcomando com a -bopção:

split -b 1024m file.tar.gz

Ele pode ser remontado em uma máquina Windows usando a resposta de @ Joshua .

copy /b file1 + file2 + file3 + file4 filetogether

Edit : Como @Charlie afirmou no comentário abaixo, convém definir um prefixo explicitamente, pois ele será usado de xoutra forma, o que pode ser confuso.

split -b 1024m "file.tar.gz" "file.tar.gz.part-"

// Creates files: file.tar.gz.part-aa, file.tar.gz.part-ab, file.tar.gz.part-ac, ...

Edit : Editando a postagem porque a pergunta está fechada e a solução mais eficaz está muito próxima do conteúdo desta resposta:

# create archives
$ tar cz my_large_file_1 my_large_file_2 | split -b 1024MiB - myfiles_split.tgz_
# uncompress
$ cat myfiles_split.tgz_* | tar xz

Esta solução evita a necessidade de usar um arquivo grande intermediário ao (des) compactar. Use a opção tar -C para usar um diretório diferente para os arquivos resultantes. btw se o archive consistir em apenas um arquivo, o tar pode ser evitado e apenas o gzip usado:

# create archives
$ gzip -c my_large_file | split -b 1024MiB - myfile_split.gz_
# uncompress
$ cat myfile_split.gz_* | gunzip -c > my_large_file

Para o Windows, você pode baixar versões portadas dos mesmos comandos ou usar o cygwin.

matpie
fonte
7
se você não adicionar um prefixo como o último argumento após o nome do arquivo para dividir você obter uma saída em arquivos chamado Xaa, xab, XAC, xad ....
Charlie
@ Charlie, obrigado, atualizei minha resposta.
matpie
2
Na verdade, o uso -b 1024MiBdeu um erro de que era um número inválido de bytes. Usando --bytes=1024mobras.
Brian
E você não precisa usar catpara remontar o arquivo. Você pode usar copy /b file1 + file2 + etc..no Windows e depois copiar de volta para o Linux, e o tar pode ler o tarball remontado. Eu apenas tentei.
22714 Brian As
1
A divisão tem a opção --numeric-suffixes: use sufixos numéricos em vez de alfabéticos.
Dr. Jan-Philip Gehrcke
27

Se você estiver se separando do Linux, ainda poderá remontar no Windows.

copy /b file1 + file2 + file3 + file4 filetogether
Joshua
fonte
Você também pode usar copy /b file* filetogether- support.microsoft.com/kb/71161
ou
5
Isso funciona corretamente apenas no NTFS e se os arquivos já estiverem na ordem de classificação NTFS. Experimente em FAT ou FAT32 = boom.
Joshua
+1 verifique se os arquivos estão na ordem certa!
Brian
@ Joshua Para ser justo, se não for, você fez um trabalho ruim na nomeação.
jpmc26
@ jpmc26: Você conhece os maus hábitos de reordenação de diretórios do FAT32, certo?
Joshua
8

Código testado, cria inicialmente um único arquivo morto e depois o divide:

 gzip -c file.orig > file.gz
 CHUNKSIZE=1073741824
 PARTCNT=$[$(stat -c%s file.gz) / $CHUNKSIZE]

 # the remainder is taken care of, for example for
 # 1 GiB + 1 bytes PARTCNT is 1 and seq 0 $PARTCNT covers
 # all of file
 for n in `seq 0 $PARTCNT`
 do
       dd if=file.gz of=part.$n bs=$CHUNKSIZE skip=$n count=1
 done

Essa variante omite a criação de um único arquivo e vai direto para a criação de partes:

gzip -c file.orig |
    ( CHUNKSIZE=1073741824;
        i=0;
        while true; do
            i=$[i+1];
            head -c "$CHUNKSIZE" > "part.$i";
            [ "$CHUNKSIZE" -eq $(stat -c%s "part.$i") ] || break;
        done; )

Nesta variante, se o tamanho do arquivo do arquivo for divisível por $CHUNKSIZE, o último arquivo parcial terá o tamanho de 0 bytes.

Adrian Panasiuk
fonte
1
Isso é o splitque já faz.
ephemient
1
Ephemient Ei, eu cavei um post procurando exatamente por isso. Não tenho comandos de divisão nem zip / binários em um determinado dispositivo, e este funcionou perfeitamente. Vou preparar este código para funcionar como comando de divisão :). Muito obrigado, @Adrian Panasiuk. Isso é perfeito para mim.
M3nda 04/03
@ erm3nda De nada, que bom que ajuda!
Adrian Panasiuk
Mas, eu testei e o resultado foi um arquivo completo, não dividido. Como pode ser? Era um arquivo grande em um dispositivo pequeno, assim como um processo longo. Teste suas soluções ao postar :(
m3nda 5/15/15
@ erm3nda Você nunca nos disse que precisava evitar criar um arquivo temporário! Por favor, veja a segunda variante!
Adrian Panasiuk