Membuka ritsleting file yang terbang melalui pipa

40

Bisakah saya membuat unzip atau program serupa bekerja pada output standar? Situasi saya sedang mengunduh file zip, yang seharusnya membuka ritsleting dengan cepat.

Masalah terkait: Bagaimana cara menyalurkan file yang diunduh ke output standar dalam bash?

Alex
sumber
Ini sepertinya harus dilakukan, tetapi sepertinya hanya mungkin untuk mengekstrak zip dan menyalurkan file ke perintah lain jika zip hanya berisi satu file. Saya ingin mengekstrak file tertentu dari zip multi-file. Alih-alih perpipaan, saya beralih ke chaining beberapa perintah 'unzip file.zip / path / file && dostuff / path / file && rm -rf / path' Meskipun tidak menjawab pertanyaan asli, dan menghasilkan file sementara yang dibuat, itu memuaskan saya perlu.
Stan Kurdziel
Lihatlah pigz. Kami menggunakannya dalam pipa. andrew.tumblr.com/post/2316602611
dmourati

Jawaban:

22

Walaupun file zip sebenarnya adalah format kontainer, tidak ada alasan mengapa itu tidak dapat dibaca dari sebuah pipa (stdin) jika file tersebut dapat masuk ke dalam memori dengan cukup mudah. Berikut skrip Python yang mengambil file zip sebagai input standar dan mengekstraksi konten ke direktori saat ini atau ke direktori yang ditentukan jika ditentukan.

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)

Script ini dapat diperkecil menjadi satu baris dan dibuat sebagai alias.

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 '.')\""

Sekarang unzip output wget dengan mudah.

wget http://your.domain.com/your/file.zip -O - | unzip-stdin target_dir
Jason R. Coombs
sumber
1
Anda dan python rock !!!
Farid Nouri Neshat
4
Satu kalimat bagus, dan +1 untuk menyebutkan bahwa file tersebut harus sesuai dengan memori. (Sayangnya tidak ada cara untuk unzip file pkzip karena struktur format file).
lxgr
2
perlu diingat ini buffer semuanya dalam ingatan sebelum mengekstraksi
William Casarin
1
tidak ada alasan mengapa itu tidak dapat dibaca sebagai aliran jika file dapat masuk ke dalam memori dengan cukup mudah tidak benar-benar akurat. Alasan mengapa Anda dipaksa untuk buffer seluruh arsip zip dalam memori sebelum Anda mengekstrak konten secara khusus karena tidak dapat dibaca sebagai stream. Tentu saja, masih bisa bermanfaat untuk menghindari penulisan arsip zip ke file.
Håkan Lindqvist
Ini bukan aliran, Anda membaca seluruh file di memori dengan menggunakan .read()metode
Romuald Brunet
18

Ini tidak mungkin berhasil seperti yang Anda harapkan. Zip bukan hanya format kompresi, tetapi juga format wadah. Ini menggulung pekerjaan tar dan gzip.bzip2 menjadi satu. Karena itu, jika zip Anda memiliki satu file, Anda dapat menggunakan unzip -p untuk mengekstrak file ke stdout. Jika Anda memiliki lebih dari satu file, tidak ada cara bagi Anda untuk mengetahui di mana mereka mulai dan berhenti.

Sedangkan untuk membaca dari stdin, halaman manual unzip memiliki kalimat ini:

Arsip yang dibaca dari input standar belum didukung, kecuali dengan funzip (dan kemudian hanya anggota arsip pertama yang dapat diekstraksi).

Anda mungkin beruntung dengan funzip.

David Pashley
sumber
Jika zip memiliki banyak file di dalamnya, maka -p dapat mencetak satu file menggunakan nama file sebagai parameter: unzip -p temp.zip file-inside-zip
Taavi Ilves
7

Apa yang ingin Anda lakukan adalah, membuat unzipmengambil file ZIP pada input standar dan bukan sebagai argumen. Ini biasanya mudah didukung oleh gzipdan tarjenis alat dengan -argumen. Tetapi standar unziptidak melakukan itu (meskipun, itu mendukung ekstraksi ke pipa). Namun, semuanya tidak hilang ...

Lihat halaman manual funzip .

funzip tanpa argumen file bertindak sebagai filter; yaitu, diasumsikan bahwa arsip ZIP (atau file gzip) sedang disalurkan ke input standar, dan mengekstrak anggota pertama dari arsip ke stdout. Ketika stdin berasal dari perangkat tty, funzip mengasumsikan bahwa ini bukan aliran data terkompresi (biner) dan menampilkan teks bantuan singkat. Jika ada argumen file, maka input dibaca dari file yang ditentukan dan bukan dari stdin.

Mengingat keterbatasan pada ekstraksi anggota tunggal, funzip paling berguna dalam hubungannya dengan program pengarsipan sekunder seperti tar (1). Bagian berikut termasuk contoh yang menggambarkan penggunaan ini dalam hal cadangan disk untuk direkam.

Ini berjalan baik dengan gagasan bahwa sebagian besar arsip linux biasanya TAR'ed dan kemudian ZIP dalam beberapa cara (gzip, bzip, et al). Ini akan bekerja untuk Anda jika Anda punya tar.ZIP.


Perlu dicatat bahwa funzipini ditulis oleh penulis asli Info-ZIP Mark Adler. Dia menulis di halaman manual funzip,

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

Namun, tidak ada pembaruan seperti itu terlihat di sekitar. Saya menduga bahwa Markus merasa tidak perlu karena metode pengarsipan lainnya bekerja dengan mudah dengan TAR.

nik
sumber
Hanya komentar; beberapa orang ingin python atau bahasa apa pun sebagai opsi unzip. Contoh utama adalah Heroku yang tidak memasukkan tar atau unzip pada sistemnya. Cara mengatasinya adalah menggunakan jar dengan menginstal Java yang diizinkan.
Nick
Ada lebih banyak tentang berurusan dengan batasan funzip dan alat serupa (khususnya hanya mampu menunjukkan anggota arsip pertama) dalam jawaban ini: unix.stackexchange.com/a/211286/77539
Joshua Goldberg
6

Saya suka menggunakan curl karena diinstal secara default ( -Ldiperlukan untuk pengalihan yang sering terjadi):

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

Namun, bsdtartidak diinstal secara default, dan saya tidak bisa mulai funzipbekerja.

Todd Partridge
sumber
Juga berfungsi dengan baik dengan beberapa file
jonnor
5

Ini adalah repost dari jawaban saya untuk pertanyaan serupa:

Format file ZIP termasuk direktori (indeks) di akhir arsip. Direktori ini mengatakan di mana, di dalam arsip, setiap file berada dan dengan demikian memungkinkan akses cepat dan acak, tanpa membaca seluruh arsip.

Ini akan muncul untuk menimbulkan masalah ketika mencoba membaca arsip ZIP melalui pipa, di mana indeks tidak diakses sampai akhir sehingga anggota individu tidak dapat diekstraksi dengan benar sampai setelah file telah sepenuhnya dibaca dan tidak lagi tersedia . Dengan demikian tampaknya tidak mengejutkan bahwa sebagian besar dekompresi ZIP gagal ketika arsip dipasok melalui pipa.

Direktori di akhir arsip bukan satu - satunya lokasi di mana informasi meta file disimpan dalam arsip. Selain itu, setiap entri juga menyertakan informasi ini di header file lokal, untuk tujuan redundansi.

Meskipun tidak setiap dekompresor ZIP akan menggunakan header file lokal ketika indeks tidak tersedia, tar dan cpio depan berakhir ke libarchive (alias bsdtar dan bsdcpio) dapat dan akan melakukannya saat membaca melalui pipa, yang berarti bahwa hal berikut mungkin terjadi:

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

Tidak mungkin dengan Info-Zip yang merupakan implementasi OSS paling umum. Lebih penting lagi, itu tidak direkomendasikan karena konstruksi arsip ZIP.

Jika perubahan format dapat dilakukan untuk Anda, maka pertimbangkan untuk menggunakan tar (1). Cukup senang dengan input / output yang dialirkan dan, pada kenyataannya, mengharapkannya secara default.

Selain itu, Anda sering dapat mengetahui apakah aplikasi mengharapkan input / output yang dialirkan dengan menentukan "-" untuk nama file. Info-Zip, seperti yang dapat Anda bayangkan, tidak memperlakukan ini sebagai argumen yang valid.

Dan Carley
sumber
4

Di zsh, Anda dapat melakukan hal berikut:

unzip =( curl http://example.com/someZipFile.zip )
Ian Robertson
sumber
3

Utilitas umum paling sederhana yang tersedia yang akan melakukan ini adalah jar, yang akan menganggap STDIN sedang digunakan jika Anda tidak memberikan file args. Itu juga membutuhkan argumen yang mirip dengan tarprogram untuk operasi.

misal, daftar isi arsip

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

Walaupun Java tidak selalu terinstal, pada mesin-mesin di mana ia berada, jarjelas merupakan metode yang paling nyaman untuk melakukan ini.

Adrian
sumber
3

Repost jawaban saya :

BusyBox's unzipdapat mengambil stdin dan mengekstrak semua file.

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

Tanda hubung unzipadalah menggunakan stdin sebagai input.

Anda bahkan bisa,

cat file.zip | busybox unzip -

Tapi itu hanya mubazir unzip file.zip.

Jika distro Anda menggunakan BusyBox secara default (misalnya Alpine), jalankan saja unzip -.

Saftever
sumber
1

Saya benar-benar membutuhkan sesuatu yang sedikit lebih rumit - mengekstrak file tertentu jika ada. Kesulitannya, aliran file input mungkin bukan file zip, dan dalam hal ini, saya membutuhkannya untuk melanjutkan melalui pipa. Inilah solusi saya (sebagian besar berkat solusi 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)"

Saya menyimpan ini sebagai file bernama "effpoptp" (bukan nama sederhana) di folder "/ bin" di komputer saya jadi mengujinya seperti ini:

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

Tujuannya adalah untuk mengontrol file MySQL Workbench versi, di mana file tersebut bisa menjadi file xml bernama sebagai file workbench, atau file workbench lengkap.

SEoF
sumber