Jak przekierować wyjście wget jako dane wejściowe do rozpakowania?

131

Muszę pobrać plik z tego linku . Pobrany plik to plik zip, który będę musiał rozpakować w bieżącym folderze.

Zwykle najpierw pobrałbym go, a następnie uruchomił polecenie unzip.

$ wget http://www.vim.org/scripts/download_script.php?src_id=11834 -O temp.zip
$ unzip temp.zip

Ale w ten sposób muszę wykonać dwa polecenia, poczekać na zakończenie pierwszego, aby wykonać następne, a także muszę znać nazwę pliku, temp.zipaby go przekazać unzip.

Czy można przekierować wyjście wgetdo unzip? Coś jak

$ unzip < `wget http://www.vim.org/scripts/download_script.php?src_id=11834`

Ale to nie zadziałało.

bash wget http://www.vim.org/scripts/download_script.php?src_id=11834 -O temp.zip:: niejednoznaczne przekierowanie

Ponadto wgetwykonano dwukrotnie i dwukrotnie pobrałem plik.

Andrew-Dufresne
źródło
W drugim przykładzie prawdopodobnie wget został wykonany dwukrotnie, ponieważ? jest postacią specjalną w powłoce. Umieszczenie adresu URL w „” s powinno pomóc.
p-statyczny
Ten wątek wydaje się mieć rozwiązanie. Jednak sam tego nie próbowałem. serverfault.com/questions/26474/…

Odpowiedzi:

96

Musisz pobrać pliki do pliku tymczasowego, ponieważ (cytując stronę podręczną rozpakowania):

Archiwa odczytane ze standardowego wejścia nie są jeszcze obsługiwane, z wyjątkiem funzip (wtedy można wyodrębnić tylko pierwszego członka archiwum).

Po prostu połącz polecenia:

wget http://www.vim.org/scripts/download_script.php?src_id=11834 -O temp.zip; unzip temp.zip; rm temp.zip

Ale aby uczynić go bardziej elastycznym, powinieneś prawdopodobnie umieścić go w skrypcie, aby zaoszczędzić trochę pisania i aby uniknąć przypadkowego nadpisania czegoś, możesz użyć mktemppolecenia do utworzenia bezpiecznej nazwy pliku tymczasowego:

#!/bin/bash
TMPFILE=`mktemp`
PWD=`pwd`
wget "$1" -O $TMPFILE
unzip -d $PWD $TMPFILE
rm $TMPFILE
tante
źródło
Czy wget file.zip && unzip file.zipto samo wget file.zip; unzip file.ziplub jedno jest preferowane nad drugim? Dzięki :)
jaggedsoft
7
@NextLocal wget && unzipuruchomi rozpakowanie tylko wtedy, gdy wget się powiedzie. wget ; unzipi tak uruchomi rozpakowanie, prawdopodobnie wskazując na nieistniejący plik.
temoto
funzip był odpowiedzią, której szukałem. Terraform (z jakiegoś powodu) pakuje binarnie jako pojedynczy plik w archiwum zip, więc było to dla mnie idealne.
Asfand Qazi
74

Oto odpowiedź mojej odpowiedzi na podobne pytanie:

Format pliku ZIP zawiera katalog (indeks) na końcu archiwum. Ten katalog mówi, gdzie w archiwum znajduje się każdy plik, a zatem umożliwia szybki, losowy dostęp, bez odczytywania całego archiwum.

Wydaje się, że stanowi to problem przy próbie odczytania archiwum ZIP przez potok, ponieważ indeks nie jest dostępny do samego końca, a zatem poszczególne elementy nie mogą zostać poprawnie wyodrębnione, dopóki plik nie zostanie całkowicie odczytany i nie będzie już dostępny . Nic dziwnego, że większość dekompresorów ZIP po prostu zawodzi, gdy archiwum jest dostarczane przez potok.

Katalog na końcu archiwum nie jest jedynym miejscem, w którym meta informacje o pliku są przechowywane w archiwum. Ponadto poszczególne wpisy zawierają również te informacje w lokalnym nagłówku pliku w celu zapewnienia nadmiarowości.

Chociaż nie każdy dekompresor ZIP będzie używał lokalnych nagłówków plików, gdy indeks jest niedostępny, interfejsy tar i cpio do libarchive (aka bsdtar i bsdcpio) mogą i będą to robić podczas czytania przez potok, co oznacza, że ​​możliwe są:

wget -qO- http://example.org/file.zip | bsdtar -xvf-
ruario
źródło
1
To jest wspaniałe! Chciałbym zauważyć, że tar daje mi ostrzeżenia o tym, że nieskompresowane dane mają niewłaściwy rozmiar (oczekiwane 0), ale same pliki wydają się nieuszkodzone. Zgadywanie wynika z braku indeksu.
Wyatt8740,
1
Mam tutaj plik .zip-file zawierający pliki z uprawnieniami do wykonywania. Kiedy pobieram i wprowadzam do gry bsdtar, bity exec są wyrzucane. Kiedy pobieram na dysk i rozpakowuję za pomocą bsdtarlub unzipwtedy, bity exec są honorowane.
Golar Ramblar
//, @GolarRamblar, czy kiedykolwiek dowiedziałeś się, dlaczego?
Nathan Basanese
1
@NathanBasanese: oto odpowiedź. W skrócie: Archiwum ZIP ma dwa miejsca, w których przechowuje takie informacje, które mogą być niespójne, a w zależności od tego, czy plik się bsdtarotworzy, jest widoczny, czy nie, używa jednego lub drugiego miejsca.
Golar Ramblar,
20

Jeśli masz zainstalowany JDK, możesz użyć jar:

wget -qO- http://example.org/file.zip | jar xvf /dev/stdin
Rory Hunter
źródło
3
Właśnie odkryłem, że jarnie zachowuje uprawnień do plików. W przeciwnym razie fajna sztuczka.
phunehehe,
7
Nie musisz podawać parametrów pliku, po prostu użyj| jar xv
cricket_007
15

Nie sądzę, żebyś nawet chciał zawracać głowę przesyłaniem wyjścia wgeta do rozpakowania.

Z artykułu w Wikipedii „ZIP (format pliku)” :

Plik ZIP jest identyfikowany przez obecność centralnego katalogu znajdującego się na końcu pliku.

wget musi całkowicie zakończyć pobieranie, zanim rozpakowanie będzie w stanie wykonać jakąkolwiek pracę, więc działają one sekwencyjnie, bez przeplatania się, jak mogłoby się wydawać.

Bruce Ediger
źródło
10

Prawidłowa składnia to:

$ unzip <(curl -sL https://www.winpcap.org/archive/1.0-docs.zip)

ale to nie zadziała z powodu błędu ( Info-ZIP w Debianie ):

lseek(3, 0, SEEK_SET)                   = -1 ESPIPE (Illegal seek)

Archive:  /dev/fd/63
  End-of-central-directory signature not found.  Either this file is not
  a zipfile, or it constitutes one disk of a multi-part archive.  In the
  latter case the central directory and zipfile comment will be found on
  the last disk(s) of this archive.
unzip:  cannot find zipfile directory in one of /dev/fd/63 or
        /dev/fd/63.zip, and cannot find /dev/fd/63.ZIP, period.

lub w BSD / OS X:

Trying to read large file (> 2 GiB) without large file support

Wynika to z faktu, że standardowe narzędzia zip używają głównie lseekfunkcji w celu ustawienia przesunięcia pliku na końcu w celu odczytania końca rekordu centralnego katalogu . Znajduje się na końcu struktury archiwum i konieczne jest odczytanie listy plików (patrz: Struktura formatu pliku zip ). Dlatego plik nie może być FIFO, potokiem, urządzeniem końcowym ani żadną inną dynamiką, ponieważ funkcja nie może pozycjonować obiektu wejściowego lseek.

Masz więc następujące obejścia:

  • użyj innego rodzaju kompresji (np. tar.gz),
  • musisz użyć dwóch osobnych poleceń,
  • użyj alternatywnych narzędzi (jak sugerowano w innych odpowiedziach),
  • utwórz alias lub funkcję, aby użyć wielu poleceń.
kenorb
źródło
Myślę, że nadal może to być FIFO. Musisz tylko czytać od FIFO do EOF (efektywnie buforując cały FIFO w pamięci lub w pliku tymczasowym). Całkowicie wykonalne, aby ułatwić tworzenie skryptów, ale niezbyt przydatne.
Evan Carroll,
8

Repost mojej odpowiedzi :

BusyBox unzipmoże zająć standardowe wejście i wyodrębnić wszystkie pliki.

wget -qO- http://downloads.wordpress.org/plugin/akismet.2.5.3.zip | busybox unzip -

Myślnikiem po unzipjest użycie stdin jako danych wejściowych.

Możesz nawet,

cat file.zip | busybox unzip -

Ale to po prostu zbędne unzip file.zip.

Jeśli twoja dystrybucja domyślnie korzysta z BusyBox (np. Alpine), po prostu uruchom unzip -.

Saftever
źródło
Bardzo przydatna sztuczka, dzięki!
Brice
-1

Działa to dla mnie całkiem dobrze:

tar xvf <(curl -sL http://www.vim.org/scripts/download_script.php?src_id=11834)

jar xvf <(curl -sL http://www.vim.org/scripts/download_script.php?src_id=11834)

wget -qO- http://www.vim.org/scripts/download_script.php?src_id=11834 | tar xvf -

wget -qO- http://www.vim.org/scripts/download_script.php?src_id=11834 | jar xvf -
Maksim Kostromin
źródło