Ekstrakcja plików .gz zawartych w folderze


13

Mam folder zawierający około 320116 plików .pdb.gz. Chcę je wszystkie zdekompresować. Jeśli użyję gunzip * .gz, pojawia się błąd, tzn. Lista argumentów jest za długa. Folder ma około 2 GB. Proszę o odpowiednią sugestię.


Jeśli będziesz musiał długo pracować nad tą strukturą katalogów, podziel ten katalog na wiele. Na przykład na podstawie czasu modyfikacji plików lub nazwy pliku.
dan

Tak, muszę pracować długoterminowo. zostały wyodrębnione teraz Chcę podzielić i podzielić je na trzy foldery na podstawie ich nazw. Czy można to zrobić za pomocą skryptu powłoki?
Lily Sharpton,

Sugeruję, abyś tam poszukał podobnych pytań. Jeśli nie znajdziesz takiego, który odpowiada Twoim potrzebom, zadaj nowe pytanie.
dan

Odpowiedzi:


25
find . -name '*.pdb.gz' -exec gunzip {} +

-exec gunzip {} +zapewni gunzipwiele, ale nie za dużo nazw plików w wierszu poleceń. Jest to bardziej wydajne niż w przypadku, -exec gunzip {} \;gdy rozpoczyna się nowy gunzipproces dla każdego pliku.


3
Jeden find, mniej gunzip!
dan

2
Zauważ, że „+” to GNUism i dlatego nie będzie działać na systemach innych niż GNU, takich jak * BSD.
Przywróć Monikę - M. Schröder

3
Późniejsze wersje BSD findumożliwiają zapis „+”. Zobacz na przykład stronę podręcznika użytkownika finddla BSD 10.1 . Dotyczy to również OS X (10.9 i przynajmniej później, może wcześniej).
plazma

7

Ilekroć pojawią się błędy „zbyt długiej listy argumentów”, możesz obejść ją, wielokrotnie wywołując żądane polecenie, za każdym razem z podzbiorem argumentów, których chcesz użyć. xargsto narzędzie, które pomaga to zrobić automatycznie.

find . -type f -a -name \*.pdb.gz -print0 | xargs -0 gunzip

czy to nie ma takiej samej nieefektywności jak -execdir gunzip "{}" \;np. że xargs wywoła gunzip osobno dla każdego pliku? To jest moje czytanie strony man.
gogoud

5
Nie, xargsumieści tyle nazw plików, ile zmieści się w gunziplinii poleceń. Spróbuj! echo a b c d e f | xargs echowywołuje tylko echoraz ze wszystkimi 6 argumentami, więc widzisz jeden wiersz wyniku (chociaż całkiem bezużyteczne polecenie do wykonania !!!!), a jeśli wymusisz podanie xargstylko 3 argumentów na wywołanie polecenia za pomocą, echo a b c d e f | xargs -n 3 echowtedy otrzymasz 2 wiersze wyniku .
Celada,

4
Kolejną zaletą używania xargsjest to, że z tą -Popcją możesz uruchamiać wiele gunzipprocesów równolegle, co (w zależności od dokładnych parametrów twojego systemu) może przebiegać szybciej.
psmears

dzięki za wskaźnik do -P@psmears. Teraz też się czegoś nauczyłem!
Celada,

1

Myślę, że to powinno działać, przekazuje ścieżkę / nazwę każdego pliku osobno do gunzip w celu przetworzenia:

find /my/dir -name "*.pdb.gz" -execdir gunzip "{}" \;

1
Spowoduje to uruchomienie gunzip raz na plik. Zobacz odpowiedź John1024 na nieco inny sposób, który pozwala uniknąć tej nieefektywności.
Celada,

@Celada To było celowe; obawiałem się, że użycie + może ponownie prowadzić do komunikatu o błędzie z powodu przeciążenia gunzip. Jeśli metoda John1024 działa, jest technicznie bardziej wydajna, ale moja powinna działać, jeśli jego nie.
gogoud

1
findz +i xargssą wyraźnie projektowane z myślą o tym właśnie problemie. Zawsze podają jak najwięcej argumentów, nie przekraczając limitu systemu operacyjnego. Bo, nawiasem mówiąc, jest to limit systemu operacyjnego, z którym nie ma nic wspólnego gunzip.
Celada

1
@Celada ok, dziękuję za te informacje, więc przypuszczalnie z „+” gunzip można wywołać więcej niż jeden raz, ale mniej niż 320 000 razy?
gogoud

1
poprawny.
Celada,

1

Wypróbuj w ten sposób:

find . -name '*.gz' -exec gunzip {} \;

3
To będzie wykonywane gunzipraz na plik. Zobacz odpowiedź John1024 na nieco inny sposób, który pozwala uniknąć tej nieefektywności.
Celada,

Pamiętaj, aby uciec z * w * .gz ...
user253751

1

Jeśli masz maszynę wielordzeniową, prawdopodobnie zauważysz, że korzystanie z niej gunzipnie zmaksymalizuje możliwości twojego komputera. W tym celu musisz uruchomić wiele gunzips równolegle. Śledzenie, które operacje są wykonywane w tym, który terminal jest ręcznie, jest uciążliwe, ale możesz to łatwo zrobić z GNU równoległym:

find . -name "*.gz" | parallel -X gunzip {}

1
Czy to nie zawiedzie, ponieważ lista argumentów do paralleljest za długa?
user253751,

@immibis Tak, zapomniałem o pierwotnym problemie, zaktualizuję swój post
Anthon

Nie będzie to jednak nie dlatego, że lista jej argumentów na findto zbyt długo?
user253751,

1
tak, ale podajesz wszystkie nazwy plików w findwierszu poleceń.
user253751,

Wydaje się, że to nie jest dobry dzień na udzielanie odpowiedzi na pytania, zapomniałem zacytować argument-name
Anthon

-1

Nie jest do findtego konieczne użycie , ponieważ nie wspomniano o podfolderach. Co musisz zrobić, to:

for f in *.gz;do gunzip $f;done

4
Ci nie muszą find, jeśli nie chcą tarło 320116 gunzipprocesów, tak jak to robi pętlę.
John WH Smith,
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.