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

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

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.


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

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

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.


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.


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.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.