Podziel pliki za pomocą tar, gz, zip lub bzip2 [zamknięte]

144

Muszę skompresować duży plik o wielkości około 17-20 GB. Muszę podzielić go na kilka plików po około 1 GB na plik.

Szukałem rozwiązania w Google i znalazłem sposoby używania poleceń spliti cat. Ale w ogóle nie działały dla dużych plików. Ponadto nie będą działać w systemie Windows; Muszę go rozpakować na komputerze z systemem Windows.

Znany jako
źródło
3
Czuję twój ból, ale to nie wydaje się być związane z programowaniem.
Jason S,
1
Wiele programów do kompresji (np. 7-Zip) jest w stanie podzielić skompresowany plik na woluminy o określonym rozmiarze, aby ułatwić dystrybucję.
Martin Liversage,
To należy do superuser.com, ale prywatna beta zaczyna się dopiero jutro, jak mi powiedziano.
JesperE
Czy mogę zapytać, dlaczego potrzebujesz skompresować ten plik?
Jan Jungnickel
Jeśli jedno z dwóch opłacalnych rozwiązań zamieszczonych tutaj nie zadziała, będzie potrzebował rozwiązania programistycznego.
Joshua

Odpowiedzi:

253

Możesz użyć splitpolecenia z -bopcją:

split -b 1024m file.tar.gz

Można go ponownie złożyć na komputerze z systemem Windows, używając odpowiedzi @ Joshua .

copy /b file1 + file2 + file3 + file4 filetogether

Edycja : Jak stwierdził @Charlie w poniższym komentarzu, możesz chcieć jawnie ustawić przedrostek, ponieważ użyje on xinaczej, co może być mylące.

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, ...

Edycja : edycja posta, ponieważ pytanie jest zamknięte, a najbardziej efektywne rozwiązanie jest bardzo zbliżone do treści tej odpowiedzi:

# 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

To rozwiązanie pozwala uniknąć używania dużego pliku pośredniego podczas (de) kompresji. Użyj opcji tar -C, aby użyć innego katalogu dla plików wynikowych. btw jeśli archiwum składa się tylko z jednego pliku, można uniknąć tar i używać tylko gzip:

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

W przypadku systemu Windows możesz pobrać przeniesione wersje tych samych poleceń lub użyć cygwin.

matpie
źródło
7
jeśli nie dodasz przedrostka jako ostatniego argumentu po nazwie pliku do podziału, otrzymasz dane wyjściowe w plikach o nazwach xaa, xab, xac, xad ....
Charlie
@Charlie, dzięki, zaktualizowałem moją odpowiedź.
matpie
2
W rzeczywistości użycie -b 1024MiBspowodowało błąd, że była to nieprawidłowa liczba bajtów. Korzystanie z --bytes=1024mutworów.
Brian
I nie musisz używać go catdo ponownego złożenia pliku. Możesz użyć copy /b file1 + file2 + etc..w systemie Windows, a następnie skopiować z powrotem do Linuksa i tar może odczytać ponownie zmontowane archiwum. Właśnie tego spróbowałem.
Brian
1
Split ma opcję --numeric-suffixes: użyj numerycznych sufiksów zamiast alfabetycznych.
Dr Jan-Philip Gehrcke
27

Jeśli dzielisz się z Linuksem, nadal możesz ponownie złożyć w systemie Windows.

copy /b file1 + file2 + file3 + file4 filetogether
Joshua
źródło
Możesz również użyć copy /b file* filetogether- support.microsoft.com/kb/71161
eug
5
Działa to poprawnie tylko na NTFS i jeśli pliki są już w porządku sortowania NTFS. Wypróbuj na FAT lub FAT32 = boom.
Joshua,
+1 upewnij się, że pliki są w odpowiedniej kolejności!
Brian
@Joshua Aby być uczciwym, jeśli nie, wykonałeś kiepską robotę.
jpmc26
@ jpmc26: Wiesz o złych nawykach zmiany kolejności katalogów w FAT32, prawda?
Joshua,
8

Testowany kod, początkowo tworzy pojedynczy plik archiwum, a następnie dzieli go:

 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

Ten wariant pomija tworzenie pojedynczego pliku archiwum i przechodzi bezpośrednio do tworzenia części:

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; )

W tym wariancie, jeśli rozmiar pliku archiwum jest podzielny przez $CHUNKSIZE, to ostatni plik częściowy będzie miał rozmiar 0 bajtów.

Adrian Panasiuk
źródło
1
To splitjuż się dzieje.
ephemient
1
ephemient Hej, mam wpis szukający właśnie tego. Nie mam poleceń / plików binarnych dzielenia ani zip na pewnym urządzeniu, a ten działał idealnie. Przygotuję ten kod do pracy jako polecenie split :). Dziękuję bardzo @Adrian Panasiuk. To dla mnie idealne.
m3nda
@ erm3nda Nie ma za co, cieszę się, że to pomaga!
Adrian Panasiuk
Ale przetestowałem i wynikiem był pełny plik, a nie podzielony. Jak to możliwe? Był to duży plik na małym urządzeniu, więc był to długi proces. Przetestuj swoje rozwiązania, wysyłając :(
m3nda
@ erm3nda Nigdy nam nie powiedziałeś, że musisz unikać tworzenia pliku tymczasowego! Zobacz drugi wariant!
Adrian Panasiuk