Dekompresowanie wielu plików jednocześnie

27

Mam ponad 200 .zipplików w jednym folderze. Nie chcę dekompresować tych jeden po drugim. Chcę wyodrębnić te przy użyciu pojedynczego polecenia lub skryptu. Jak to zrobić.

g_p
źródło

Odpowiedzi:

38

Jeśli naprawdę chcesz je rozpakować równolegle, możesz to zrobić

for i in *zip; do unzip "$i" & done

To jednak uruchomi N procesów dla plików .zip i może być bardzo ciężkie dla twojego systemu. Aby uzyskać bardziej kontrolowane podejście, uruchamiając jednocześnie tylko 10 równoległych procesów, wypróbuj to:

find . -name '*.zip' -print0 | xargs -0 -I {} -P 10 unzip {}

Aby kontrolować liczbę uruchomionych równoległych procesów, zmień -Pna cokolwiek chcesz. Jeśli nie chcesz, aby rekursje następowały w podkatalogach, zrób to zamiast tego:

find . -maxdepth 1 -name '*.zip' -print0 | xargs -0 -I {} -P 10 unzip {}

Alternatywnie możesz zainstalować GNU równolegle, jak sugeruje @OleTange w komentarzach i uruchomić

parallel unzip ::: *zip
terdon
źródło
3
Równoległe działanie to dobry pomysł, ale czy dyskowe operacje we / wy nie będą głównym wąskim gardłem?
Paddy Landau
1
@PaddyLandau nie jestem pewien, musiałbym to sprawdzić. Będzie to zależeć od szybkości algorytmu dekompresyjnego w zależności od prędkości dysku, jaki sobie wyobrażam.
terdon
Użyj -execlub -execdirzamiast rurowania do xargs. Jest nie tylko łatwiejszy do zrozumienia, ale także mniej podatny na błędy i zużywa mniej zasobów systemowych. find . -name '*.zip' -exec unzip {} ';'(Musisz zacytować średnik).
Paddy Landau
@PaddyLandau jedynym powodem, dla którego przesyłam strumieniowo do xargs, jest równoległe uruchamianie rzeczy, tak jak poprosił OP. -exec \;(możesz wstawić średnik, bez cudzysłowu), uruchomi każde polecenie sekwencyjnie. -exec +jest lepsze, ale tutaj nie będzie działać, ponieważ nie tak to unzipdziała.
terdon
Myślę, że różnie rozumieliśmy PO. Czytasz go tak, jakby chciał tego równolegle, podczas gdy ja rozumiałem, że oznacza jedno polecenie zamiast wielu poleceń. Cóż, teraz ma obie metody :)
Paddy Landau
17

Polecenie równoległe GNU jest dobrze dostosowane do tego typu rzeczy. Po:

$ sudo apt-get install parallel

Następnie

ls *.zip | parallel unzip

Spowoduje to użycie tyle rdzeni, ile masz, utrzymując każdy rdzeń zajęty rozpakowaniem, dopóki wszystkie nie zostaną zakończone.

Wayne Conrad
źródło
Lepiej jest użyć echo *.zipzamiast tego, aby zapobiec wykradaniu się aliasu ls w dodatkowych informacjach. Jednak ma to ten sam problem, co odpowiedź @ Guru, psuje nazwy plików zawierające białe znaki.
nyuszika7h
1
@ nyuszika7h W przeciwieństwie do xargsGNU Parallel nie łamie nazw plików zawierających spację / tab / cytat. Tylko jeśli nazwy plików zawierają nowe linie, będziesz musiał zachować szczególną ostrożność. Na przykład, używając:parallel unzip ::: *.zip
Ole Tange
@ nyuszika7h - Są to dobre powody, aby unikać zarówno aliasingu standardowych poleceń, jak i wstawiania spacji w nazwach plików.
Wayne Conrad
@ nyuszika7h używanie echojest tak samo złe, jak używanie ls. Globbing i pętla while są najbezpieczniejsze.
terdon
1
@NateEldredge Podczas gdy ta szansa była większa w czasach, gdy systemy miały tylko jeden dysk magnetyczny, obecnie w przypadku macierzy RAID z wieloma wrzecionami i dyskiem flash ta szansa jest mniejsza. Najlepiej jest oczywiście zmierzyć i zobaczyć, jak zachowuje się twój system. Niedawno użyłem macierzy RAID o 40 wrzecionach, w których optymalna równoległość dla procesów głodnych we / wy wynosiła 10: Nie dawała 10-krotnego przyspieszenia - tylko 6-krotnie, ale mniej niż 10 procesów dało mniej niż 6-krotnie.
Ole Tange
12

Możesz użyć następującego polecenia:

Najpierw zmień katalog w terminalu na katalog zawierający pliki .zip:

cd /path

Następnie uruchom to polecenie, aby rozpakować wszystkie pliki .zip:

for z in *.zip; do unzip "$z"; done
nux
źródło
10

Jeśli masz wiele .zipplików w folderze i chcesz je zdekompresować, otwórz terminal i przejdź do folderu, używając:

cd <path_to_folder>

Teraz użyj tego polecenia, aby zdekompresować cały .zipplik:

ls *.zip | xargs -n1 unzip
g_p
źródło
3
Nie powiedzie się, jeśli którakolwiek z nazw plików zawiera spacje.
terdon
1
tak, masz rację.
g_p
Lepiej jest użyć echo *.zipzamiast tego, aby zapobiec lswykradaniu się aliasu w dodatkowych informacjach, jednak to nadal nie rozwiązuje problemu białych znaków.
nyuszika7h
1
@OleTange W przypadku, gdy nie zauważyłeś, powiedziałem, że nadal nie działa na nazwach plików z białymi spacjami.
nyuszika7h
1
Nigdy nie zależą od danych wyjściowych lsskryptów, ponieważ dane wyjściowe nie są dobrze zdefiniowane między wersjami. Zamiast tego spójrz na odpowiedź @terdon, która rozwiązuje wszystkie problemy tego rozwiązania.
Paddy Landau
6

Możesz użyć find z -execpodobnym,

find . -name "*.zip" -exec unzip {} \;

Działa to, jeśli plik ma spację w nazwie.

Elliott Frisch
źródło
3

Nieterminowa metoda.

Po prostu wybierz pliki zip, kliknij jeden z nich prawym przyciskiem myszy i wybierz extract here. Możesz wybrać wszystkie lub tylko kilka plików zip na raz.

Parto
źródło
1

unzip \*.zip lub unzip '*.zip'

Oczywiste unzip *.zipnie działa, ponieważ powłoka rozwija go unzip foo.zip bar.zip ...i unzipinterpretuje pierwszą nazwę pliku jako plik zip, a kolejne nazwy plików jako pliki do wyodrębnienia z tego pliku zip.

Jednak unzipjest nieco nietypowe wśród poleceń Unix, że robi swoje ekspansje glob. Jeśli *powłoka nie zostanie rozwinięta przez powłokę, rozpakuje ją i zinterpretuje wszystkie wynikowe nazwy plików jako pliki zip do przetworzenia. Więc w tym szczególnym przypadku można uciec bez forpętli xargslub tym podobnych.

Nate Eldredge
źródło