it-swarm-vi.tech

Giải nén các tập tin đang bay qua một đường ống

Tôi có thể giải nén hoặc bất kỳ chương trình tương tự nào hoạt động trên đầu ra tiêu chuẩn không? Tình huống là tôi đang tải xuống một tệp Zip, được cho là giải nén nhanh chóng.

Vấn đề liên quan: Làm cách nào để chuyển một tệp đã tải xuống thành đầu ra tiêu chuẩn trong bash?

43
Alex

Mặc dù tệp Zip trên thực tế là định dạng chứa, không có lý do nào khiến nó không thể được đọc từ một đường ống (stdin) nếu tệp có thể vừa với bộ nhớ đủ dễ dàng. Đây là một Python script lấy tệp Zip làm đầu vào tiêu chuẩn và trích xuất nội dung vào thư mục hiện tại hoặc vào một thư mục được chỉ định nếu được chỉ định.

import zipfile
import sys
import StringIO
data = StringIO.StringIO(sys.stdin.read())
z = zipfile.ZipFile(data)
dest = sys.argv[1] if len(sys.argv) == 2 else '.'
z.extractall(dest)

Kịch bản này có thể được thu nhỏ thành một dòng và được tạo thành bí danh.

alias unzip-stdin="python -c \"import zipfile,sys,StringIO;zipfile.ZipFile(StringIO.StringIO(sys.stdin.read())).extractall(sys.argv[1] if len(sys.argv) == 2 else '.')\""

Bây giờ giải nén đầu ra của wget dễ dàng.

wget http://your.domain.com/your/file.Zip -O - | unzip-stdin target_dir
22
Jason R. Coombs

Điều này không có khả năng làm việc như bạn mong đợi. Zip không chỉ là một định dạng nén, mà còn là một định dạng chứa. Nó cuộn các công việc của cả tar và gzip.bzip2 thành một. Phải nói rằng, nếu Zip của bạn có một tệp duy nhất, bạn có thể sử dụng giải nén -p để giải nén các tệp vào thiết bị xuất chuẩn. Nếu bạn có nhiều hơn một tệp, không có cách nào để bạn biết nơi chúng bắt đầu và dừng lại.

Đối với việc đọc từ stdin, trang man giải nén có câu này:

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ữ).

Bạn có thể có một số may mắn với funzip.

18
David Pashley

Những gì bạn muốn làm là, tạo unzip lấy một tệp ZIPped trên đầu vào tiêu chuẩn của nó chứ không phải là một đối số. Điều này thường dễ dàng được hỗ trợ bởi gziptar loại công cụ có - tranh luận. Nhưng tiêu chuẩn unzip không làm điều đó (mặc dù, nó hỗ trợ trích xuất vào đường ống). Tuy nhiên, tất cả là không bị mất...

Nhìn vào funzip trang hướng dẫn.

funzip không có đối số tập tin hoạt động như một bộ lọc; nghĩa là, nó giả định rằng kho lưu trữ Zip (hoặc tệp gzip'd) đang được đưa vào đầu vào tiêu chuẩn và nó trích xuất thành viên đầu tiên từ kho lưu trữ sang thiết bị xuất chuẩn. Khi stdin đến từ một thiết bị tty, funzip giả định rằng đây không thể là một luồng dữ liệu nén (nhị phân) và thay vào đó hiển thị một văn bản trợ giúp ngắn. Nếu có một đối số tệp, thì đầu vào được đọc từ tệp được chỉ định thay vì từ stdin.

Với giới hạn về trích xuất một thành viên, funzip là hữu ích nhất khi kết hợp với chương trình lưu trữ thứ cấp như tar (1). Phần sau đây bao gồm một ví dụ minh họa việc sử dụng này trong trường hợp sao lưu đĩa vào băng.

Điều này phù hợp với ý tưởng rằng hầu hết các tài liệu lưu trữ linux thường được TAR'ed và sau đó được ZIP theo một cách nào đó (gzip, bzip, et al). Điều này sẽ làm việc cho bạn nếu bạn có tar.Zip.


Điều đáng chú ý là funzip được viết bởi tác giả gốc Info-Zip Mark Adler. Ông viết trong trang người đàn ông funzip,

this functionality should be incorporated into unzip itself (future release).

tuy nhiên, không có cập nhật như vậy được nhìn thấy xung quanh. Tôi nghi ngờ rằng Mark thấy không cần thiết vì các phương thức lưu trữ khác hoạt động dễ dàng với TAR.

7
nik

Tôi thích sử dụng curl vì nó được cài đặt theo mặc định (-L là cần thiết cho các chuyển hướng thường xảy ra):

curl -L http://example.com/file.Zip | bsdtar -xvf - -C /path/to/directory/

Tuy nhiên, bsdtar không được cài đặt theo mặc định và tôi không thể làm cho funzip hoạt động.

7
Todd Partridge

Đây là một repost của 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 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à do đó, 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í chỉ nơi 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 thành 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-
5
ruario

Trong zsh, bạn có thể làm như sau:

unzip =( curl http://example.com/someZipFile.Zip )
4
Ian Robertson

Tiện ích phổ biến đơn giản nhất có sẵn sẽ thực hiện điều này là jar, sẽ cho rằng STDIN đang được sử dụng nếu bạn vượt qua nó không có tệp nào tranh luận. Nó cũng nhận các đối số tương tự như chương trình tar cho các hoạt động.

ví dụ. liệt kê nội dung của một kho lưu trữ

curl https://my.example.com/file.Zip | jar t

Mặc dù Java không phải lúc nào cũng được cài đặt, nhưng trên các máy đó, jar chắc chắn là phương pháp thuận tiện nhất để thực hiện việc này.

4
Adrian

Info-Zip không thể thực hiện được, đây là cách triển khai OSS phổ biến nhất. Quan trọng hơn, mặc dù vậy, nó không được khuyến khích do các cấu trúc của kho lưu trữ Zip.

Nếu thay đổi định dạng là khả thi với bạn thì hãy xem xét sử dụng tar (1) thay thế. Nó khá hài lòng với đầu vào/đầu ra được truyền phát và trên thực tế, mong đợi nó theo mặc định.

Ngoài ra, bạn thường có thể biết liệu các ứng dụng có mong đợi đầu vào/đầu ra được truyền phát hay không bằng cách chỉ định "-" cho tên tệp. Info-Zip, như bạn có thể tưởng tượng, không coi đây là một đối số hợp lệ.

4
Dan Carley

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

BusyBox's unzip có 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 unzip là 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 củ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 -.

3
Saftever

Tôi thực sự cần một cái gì đó phức tạp hơn một chút - giải nén một tệp cụ thể nếu nó tồn tại. Khó khăn là, luồng tệp đầu vào có thể không phải là tệp Zip và trong trường hợp đó, tôi cần nó để tiếp tục qua đường ống. Đây là giải pháp của tôi (chủ yếu nhờ vào giải pháp Jason R. Coombs)

python -c "import zipfile,sys,StringIO
data=sys.stdin.read()
try:
    z=zipfile.ZipFile(StringIO.StringIO(data))
    z.open(\"$1\")
    sys.stdout.write(z.read(\"$1\"))
except (RuntimeError, zipfile.BadZipfile):
    sys.stdout.write(data)"

Tôi đã lưu tệp này dưới dạng tệp có tên "effpoptp" (không phải tên đơn giản) trong thư mục "/ bin" trên máy của mình để kiểm tra nó giống như vậy:

cat defaultModel.mwb|effpoptp "document.mwb.xml"

Mục đích là để kiểm soát phiên bản các tệp Workbench của MySQL, trong đó tệp có thể là tệp xml có tên là tệp bàn làm việc hoặc tệp bàn làm việc hoàn chỉnh.

1
SEoF