Як перенаправити вихід wget як вхід для розпакування?


131

Я маю завантажити файл за цим посиланням . Завантаження файлу - це zip-файл, який мені доведеться розпаковувати у поточній папці.

Зазвичай я спершу його завантажую, потім виконую команду unzip.

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

Але таким чином мені потрібно виконати дві команди, дочекатися завершення першої, щоб виконати наступну, також я повинен знати ім'я файлу, temp.zipщоб надати його unzip.

Чи можна перенаправити вихід wgetна unzip? Щось на зразок

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

Але це не спрацювало.

bash wget http://www.vim.org/scripts/download_script.php?src_id=11834 -O temp.zip:: неоднозначне перенаправлення

Крім того, wgetйого виконували двічі та завантажували файл двічі.


В останньому прикладі wget, ймовірно, виконувався двічі, оскільки? є особливим персонажем в оболонці. Введення URL-адреси в "" має допомогти.
p-статичний

Здається, ця нитка має рішення. Я сам не пробував цього, хоча. serverfault.com/questions/26474/…

Відповіді:


96

Ви повинні завантажити свої файли у тимчасовий файл, оскільки (цитуючи розпаковану сторінку man):

Архів, прочитаний зі стандартного введення, ще не підтримується, за винятком функції funzip (і тоді може бути вилучений лише перший член архіву).

Просто зберіть команди разом:

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

Але для того, щоб зробити його більш гнучким, вам, ймовірно, слід вкласти його в сценарій, щоб ви зберегли деякий текст і щоб переконатися, що ви випадково не перезаписали щось, ви могли використовувати mktempкоманду для створення безпечного імені для вашого тимчасового файлу:

#!/bin/bash
TMPFILE=`mktemp`
PWD=`pwd`
wget "$1" -O $TMPFILE
unzip -d $PWD $TMPFILE
rm $TMPFILE

Чи wget file.zip && unzip file.zipте саме, wget file.zip; unzip file.zipчи є одне переважне над іншим? Дякую :)
jaggedsoft

7
@NextLocal wget && unzipзапустить розпакування, лише якщо Wget вдалося. wget ; unzipвсе одно запуститься розпакувати, можливо, вказуючи на неіснуючий файл.
темпо

funzip - відповідь, яку я шукав. Terraform (чомусь) пакує, він є двійковим як єдиний файл в zip архіві, тому це було ідеально для мене.
Асфанд Казі

74

Це репост моєї відповіді на подібне запитання:

Формат ZIP-файлу містить каталог (покажчик) в кінці архіву. У цьому каталозі зазначено, де всередині архіву розташований кожен файл, що дозволяє швидко і випадково отримати доступ, не читаючи весь архів.

Це може створити проблему при спробі прочитати ZIP-архів через трубу, оскільки до нього не можна отримати доступ до індексу до самого кінця, і тому окремі члени не можуть бути правильно вилучені до того моменту, поки файл не буде повністю прочитаний і не буде доступний. . Як таке, не дивно, що більшість декомпресорів ZIP просто виходять з ладу, коли архів подається через трубу.

Каталог в кінці архіву - не єдине місце, де мета-інформація зберігається в архіві. Крім того, окремі записи також містять цю інформацію в заголовку локального файлу для надмірності.

Хоча не кожен ZIP-декомпресор використовує локальні заголовки файлів, коли індекс недоступний, тар та cpio фронт закінчуються до лібархіву (він же bsdtar та bsdcpio), і можуть робити це під час читання через трубу, що означає, що можливе наступне:

wget -qO- http://example.org/file.zip | bsdtar -xvf-

1
Це чудово! Я зауважу, що tar дає мені попередження про те, що нестиснені дані мають невірний розмір (очікується 0), але самі файли здаються непошкодженими. Здогадка про це пов’язана з відсутністю індексу.
Wyatt8740

1
У мене .zipтут -файл, який містить файли з дозволами на виконання. Коли я завантажую і передаю в нього bsdtar, біти exec відкидаються. Коли я завантажую на диск і витягую з ним bsdtarабо unzipпотім, біти exec шануються.
Голар Рамблар

//, @GolarRamblar, ти ніколи не дізнався чому?
Натан Басанес

1
@NathanBasanese: ось відповідь. Коротше кажучи: у архіві ZIP є два місця, де він зберігає таку інформацію, яка може бути непослідовною, і залежно від того, чи bsdtarвідкриється файл, можна шукати чи ні, він використовує те чи інше місце.
Голар Рамблар

20

Якщо у вас встановлений JDK, ви можете використовувати jar:

wget -qO- http://example.org/file.zip | jar xvf /dev/stdin

3
Щойно я виявив, що jarне зберігається дозволів на файли. Хороший трюк інакше.
phunehehe

7
Вам не потрібно давати файловий парам, просто використовуйте| jar xv
cricket_007

15

Я не думаю, що ви навіть хочете заважати виводу wget-файлів у unzip.

З статті Вікіпедії "ZIP (формат файлу)" :

ZIP-файл ідентифікується за наявністю центрального каталогу, розташованого в кінці файлу.

wget повинен повністю закінчити завантаження, перш ніж unzip зможе виконати будь-яку роботу, тому вони працюють послідовно, а не переплітаються, як можна було б подумати.


10

Правильним синтаксисом було б:

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

але це не спрацює через помилку ( Info-ZIP на Debian ):

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.

або на BSD / OS X:

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

Це відбувається тому, що стандартні інструменти zip в основному використовують lseekфункцію , щоб встановити зсув файлу в кінці, щоб прочитати його кінець запису центрального каталогу . Він розташований в кінці структури архіву, і йому потрібно прочитати список файлів (див. Структуру формату файлів Zip ). Тому файл не може бути FIFO, трубою, кінцевим пристроєм або будь-яким іншим динамічним, тому що вхідний об'єкт не може бути розміщений lseekфункцією.

Отже, у вас є такі шляхи вирішення:

  • використовувати різного виду стиснення (наприклад tar.gz),
  • вам доведеться використовувати дві окремі команди,
  • використовувати альтернативні інструменти (як це пропонується в інших відповідях),
  • створити псевдонім або функцію для використання декількох команд.

Я думаю, це все-таки може бути FIFO. Вам просто доведеться продовжувати читати з FIFO до EOF (ефективно буферизуючи весь FIFO у пам'яті або у тимчасовому файлі). Цілком можливо для полегшення створення сценарію, але не дуже корисно.
Еван Керролл

8

Репост моєї відповіді :

BusyBox unzipможе приймати stdin та витягувати всі файли.

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

Тире після unzip- використовувати stdin в якості введення.

Ви навіть можете,

cat file.zip | busybox unzip -

Але це просто зайве unzip file.zip.

Якщо ваш дистрибутив використовує BusyBox за замовчуванням (наприклад, Alpine), просто запустіть unzip -.


Дуже корисна хитрість, дякую!
Бріс

-1

Це працює для мене досить добре:

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 -
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.