Làm thế nào để chuyển hướng đầu ra của wget như đầu vào để giải nén?


131

Tôi phải tải một tập tin từ liên kết này . Tải xuống tệp là một tệp zip mà tôi sẽ phải giải nén trong thư mục hiện tại.

Thông thường, tôi sẽ tải xuống trước, sau đó chạy lệnh giải nén.

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

Nhưng theo cách này, tôi cần thực thi hai lệnh, chờ hoàn thành lệnh đầu tiên để thực thi lệnh tiếp theo, đồng thời, tôi phải biết tên của tệp temp.zipđể đưa ra unzip.

Là nó có thể chuyển hướng đầu ra của wgetđể unzip? Cái gì đó như

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

Nhưng nó không hoạt động.

bash :: wget http://www.vim.org/scripts/download_script.php?src_id=11834 -O temp.zipchuyển hướng mơ hồ

Ngoài ra, wgetđã thực hiện hai lần và tải xuống tệp hai lần.


Trong ví dụ sau, wget có thể được thực thi hai lần vì? là một nhân vật đặc biệt trong vỏ. Đặt URL trong "" sẽ giúp.
p-static

Chủ đề này dường như có một giải pháp. Mặc dù vậy, tôi đã không thử nó. serverfault.com/questions/26474/

Câu trả lời:


96

Bạn phải tải các tệp của mình xuống tệp tạm thời, bởi vì (trích dẫn trang man giải nén):

Lưu trữ đọc từ đầu vào tiêu chuẩn chưa được hỗ trợ, ngoại trừ với funzip (và sau đó chỉ có thể trích xuất thành viên đầu tiên của kho lưu trữ).

Chỉ cần mang các lệnh lại với nhau:

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

Nhưng để làm cho nó linh hoạt hơn, có lẽ bạn nên đặt nó vào một tập lệnh để bạn lưu một số thao tác gõ và để đảm bảo bạn không vô tình ghi đè lên một cái gì đó bạn có thể sử dụng mktemplệnh để tạo một tên tệp an toàn cho tệp tạm thời của mình:

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

wget file.zip && unzip file.zipgiống wget file.zip; unzip file.ziphoặc được ưa thích hơn so với cái khác? Cảm ơn :)
jaggedsoft

7
@NextLocal wget && unzipsẽ chỉ giải nén nếu wget thành công. wget ; unzipdù sao cũng sẽ chạy giải nén, có thể trỏ đến tệp không tồn tại.
temoto

funzip là câu trả lời tôi đang tìm kiếm. Terraform (vì một số lý do) gói nó là tệp nhị phân dưới dạng một tệp trong kho lưu trữ zip, vì vậy điều này là hoàn hảo đối với tôi.
Asfand Qazi

74

Đây là một bài đăng lại câu trả lời của tôi cho một câu hỏi tương tự:

Định dạng tệp ZIP bao gồm một thư mục (chỉ mục) ở cuối kho lưu trữ. Thư mục này cho biết vị trí, trong kho lưu trữ, mỗi tệp được đặt và do đó cho phép truy cập nhanh, ngẫu nhiên mà không cần đọc toàn bộ tệp lưu trữ.

Điều này có vẻ gây ra vấn đề khi cố đọc tệp lưu trữ ZIP qua đường ống, trong đó chỉ mục không được truy cập cho đến khi kết thúc và vì vậy các thành viên riêng lẻ không thể được trích xuất chính xác cho đến khi tệp đã được đọc hoàn toàn và không còn khả dụng . Do đó, có vẻ không ngạc nhiên khi hầu hết các bộ giải nén ZIP chỉ đơn giản là thất bại khi kho lưu trữ được cung cấp qua một đường ống.

Thư mục ở cuối kho lưu trữ không phải là vị trí duy nhất lưu trữ thông tin meta tệp trong kho lưu trữ. Ngoài ra, các mục riêng lẻ cũng bao gồm thông tin này trong tiêu đề tệp cục bộ, cho mục đích dự phòng.

Mặc dù không phải mọi trình giải nén ZIP sẽ sử dụng các tiêu đề tệp cục bộ khi chỉ mục không khả dụng, mặt trước tar và cpio kết thúc với libarchive (còn gọi là bsdtar và bsdcpio) có thể và sẽ làm như vậy khi đọc qua một đường ống, có nghĩa là có thể sau đây:

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

1
Thật tuyệt vời! Tôi sẽ lưu ý rằng tar cung cấp cho tôi một số cảnh báo về dữ liệu không nén là kích thước sai (dự kiến ​​0), nhưng bản thân các tệp dường như không bị hư hại. Đoán điều này là do thiếu chỉ số.
Wyatt8740 17/03/18

1
Tôi có một .zip-file ở đây có chứa các tệp có quyền thực thi. Khi tôi tải xuống và chuyển vào bsdtar, các bit exec sẽ bị ném đi. Khi tôi tải xuống đĩa và giải nén bằng bsdtarhoặc unzipsau đó, các bit exec được vinh danh.
Gole Ramblar

//, @GolarRamblar, didst bao giờ tìm hiểu tại sao?
Nathan Basan

1
@NathanBasan: đây là câu trả lời. Tóm lại: Một kho lưu trữ ZIP có hai nơi lưu trữ thông tin đó, có thể không nhất quán và tùy thuộc vào việc bsdtarmở tệp có thể tìm kiếm được hay không sử dụng địa điểm này hoặc địa điểm khác.
Gole Ramblar

20

Nếu bạn đã cài đặt JDK, bạn có thể sử dụng jar:

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

3
Tôi chỉ thấy rằng jarkhông bảo vệ quyền tập tin. Đẹp lừa khác.
phunehehe

7
Bạn không cần phải cung cấp một tệp param, chỉ cần sử dụng| jar xv
cricket_007

15

Tôi không nghĩ rằng bạn thậm chí muốn làm phiền đầu ra của đường ống vào giải nén.

Từ bài viết "ZIP (định dạng tệp)" trên wikipedia :

Một tệp ZIP được xác định bởi sự hiện diện của một thư mục trung tâm nằm ở cuối tệp.

wget phải hoàn thành việc tải xuống trước khi giải nén có thể thực hiện bất kỳ công việc nào, vì vậy chúng chạy tuần tự, không đan xen như người ta nghĩ.


10

Cú pháp thích hợp sẽ là:

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

nhưng nó không hoạt động, vì lỗi ( Info-ZIP trên 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.

hoặc trên BSD / OS X:

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

Điều này là do các công cụ zip tiêu chuẩn chủ yếu sử dụng lseekchức năng để đặt bù tập tin ở cuối để đọc phần cuối của bản ghi thư mục trung tâm . Nó nằm ở cuối cấu trúc lưu trữ và cần phải đọc danh sách các tệp (xem: Cấu trúc định dạng tệp Zip ). Do đó, tệp không thể là FIFO, ống, thiết bị đầu cuối hoặc bất kỳ động nào khác, bởi vì đối tượng đầu vào không thể được định vị bởi lseekchức năng.

Vì vậy, bạn có cách giải quyết sau đây:

  • sử dụng loại nén khác nhau (ví dụ tar.gz),
  • bạn phải sử dụng hai lệnh riêng biệt
  • sử dụng các công cụ thay thế (như được đề xuất trong các câu trả lời khác),
  • tạo một bí danh hoặc hàm để sử dụng nhiều lệnh.

Tôi nghĩ rằng nó vẫn có thể là một FIFO. Bạn chỉ cần tiếp tục đọc từ FIFO cho đến khi EOF (đệm hiệu quả toàn bộ FIFO trong bộ nhớ hoặc trong tệp tạm thời). Hoàn toàn có thể làm để dễ dàng tạo kịch bản, nhưng không hữu ích lắm.
Evan Carroll

8

Đăng lại câu trả lời của tôi :

BusyBox unzipcó thể lấy stdin và giải nén tất cả các tệp.

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

Dấu gạch ngang sau unziplà sử dụng stdin làm đầu vào.

Bạn có thể,

cat file.zip | busybox unzip -

Nhưng đó chỉ là dư thừa unzip file.zip.

Nếu distro của bạn sử dụng BusyBox theo mặc định (ví dụ: Alpine), chỉ cần chạy unzip -.


Thủ thuật rất hữu ích, cảm ơn!
Brice

-1

Điều này làm việc cho tôi khá tốt:

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 -
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.