การขยายไฟล์ที่บินผ่านไปป์


39

ฉันสามารถทำให้ unzip หรือโปรแกรมที่คล้ายกันทำงานบนเอาต์พุตมาตรฐานได้หรือไม่ สถานการณ์คือฉันกำลังดาวน์โหลดไฟล์ zip ซึ่งควรจะคลายซิปทันที

ปัญหาที่เกี่ยวข้อง: ฉันจะไพพ์ไฟล์ที่ดาวน์โหลดไปยังเอาต์พุตมาตรฐานใน bash ได้อย่างไร


ดูเหมือนว่ามันควรจะทำได้ แต่ดูเหมือนว่าเป็นไปได้ที่จะแตกไฟล์ zip และไพพ์ไฟล์ไปยังคำสั่งอื่นหากไฟล์ zip มีเพียงไฟล์เดียว ฉันต้องการแยกไฟล์เฉพาะจากไฟล์ zip หลายไฟล์ แทนที่จะเปลี่ยนไปเป็นท่อฉันเปลี่ยนไปผูกมัดไฟล์ unzip หลาย ๆ คำสั่ง 'zip / path / file &&dostuff / path / file &&rm -rf / path' ขณะที่ไม่ตอบคำถามเดิมและทำให้เกิดการสร้างไฟล์ชั่วคราวฉันก็พอใจแล้ว ความต้องการ.
Stan Kurdziel

ตรวจสอบหมู เราใช้มันในท่อ andrew.tumblr.com/post/2316602611
dmourati

คำตอบ:


22

ในขณะที่ไฟล์ zip เป็นรูปแบบคอนเทนเนอร์จริง ๆ แล้วก็ไม่มีเหตุผลว่าทำไมไฟล์ zip ถึงไม่สามารถอ่านได้จากไปป์ (stdin) ถ้าไฟล์นั้นสามารถใส่ลงในหน่วยความจำได้อย่างง่ายดาย ต่อไปนี้เป็นสคริปต์ Python ที่ใช้ไฟล์ zip เป็นอินพุตมาตรฐานและแยกเนื้อหาไปยังไดเรกทอรีปัจจุบันหรือไปยังไดเรกทอรีที่ระบุหากระบุไว้

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)

สคริปต์นี้สามารถย่อให้เหลือหนึ่งบรรทัดและสร้างเป็นนามแฝง

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

ตอนนี้เปิดเครื่องรูดเอาท์พุทของ wget ได้อย่างง่ายดาย

wget http://your.domain.com/your/file.zip -O - | unzip-stdin target_dir

1
คุณกับงูหลาม !!!
Farid Nouri Neshat

3
ดีหนึ่งซับและ +1 สำหรับการกล่าวถึงว่าไฟล์จะต้องพอดีกับหน่วยความจำ (น่าเสียดายที่ไม่มีวิธีการแตกไฟล์ pkzip เนื่องจากโครงสร้างรูปแบบไฟล์)
lxgr

2
โปรดจำไว้ว่าบัฟเฟอร์นี้มีทุกอย่างในหน่วยความจำก่อนที่จะแยกออกมา
William Casarin

1
ไม่มีเหตุผลว่าทำไมจึงไม่สามารถอ่านเป็นสตรีมได้หากไฟล์สามารถพอดีกับหน่วยความจำได้ง่ายพอไม่ถูกต้องจริงๆ สาเหตุที่คุณถูกบังคับให้บัฟเฟอร์ไฟล์เก็บถาวรซิปทั้งหมดในหน่วยความจำก่อนที่คุณจะแยกเนื้อหานั้นเป็นแบบพิเศษเพราะมันไม่สามารถอ่านเป็นสตรีมได้ แน่นอนว่ามันยังมีประโยชน์ในการหลีกเลี่ยงการเขียนไฟล์ zip ไปยังไฟล์
Håkan Lindqvist

นี่ไม่ใช่กระแสคุณกำลังอ่านไฟล์ทั้งหมดในหน่วยความจำโดยใช้.read()วิธีการ
Romuald Brunet

17

สิ่งนี้ไม่น่าเป็นไปได้ตามที่คุณคาดหวัง Zip ไม่ได้เป็นเพียงรูปแบบการบีบอัดเท่านั้น แต่ยังเป็นรูปแบบคอนเทนเนอร์ด้วย มันรวมงานของ tar และ gzip.bzip2 ไว้ในที่เดียว ต้องบอกว่าหากไฟล์ zip ของคุณมีไฟล์เดียวคุณสามารถใช้ unzip -p เพื่อแตกไฟล์ไปยัง stdout หากคุณมีมากกว่าหนึ่งไฟล์คุณไม่สามารถบอกได้ว่าจะเริ่มและหยุดที่ใด

สำหรับการอ่านจาก stdin หน้า unzip man มีประโยคนี้:

ไฟล์เก็บถาวรที่อ่านจากอินพุตมาตรฐานยังไม่ได้รับการสนับสนุนยกเว้นด้วย funzip (และจากนั้นเฉพาะสมาชิกแรกของไฟล์เก็บถาวรที่สามารถแตกได้)

คุณอาจมีโชคกับ funzip


หาก zip มีไฟล์หลายไฟล์อยู่ข้างใน -p สามารถพิมพ์ไฟล์เดี่ยวโดยใช้ชื่อไฟล์เป็นพารามิเตอร์: unzip -p temp.zip ไฟล์ภายใน - ไฟล์ zip
Taavi Ilves

7

สิ่งที่คุณต้องการทำคือให้unzipนำไฟล์ ZIPped ไปที่อินพุตมาตรฐานแทนที่จะเป็นอาร์กิวเมนต์ นี้มักจะได้รับการสนับสนุนอย่างง่ายดายโดยการgzipและtarชนิดของเครื่องมือที่มี-การโต้แย้ง แต่มาตรฐานunzipไม่ได้ทำเช่นนั้น (แม้ว่าจะสนับสนุนการแยกไปยังไพพ์) อย่างไรก็ตามทั้งหมดจะไม่สูญหายไป ...

ดูหน้าคู่มือfunzip

funzip ที่ไม่มีอาร์กิวเมนต์ไฟล์ทำหน้าที่เป็นตัวกรอง นั่นคือมันสันนิษฐานว่าไฟล์ ZIP (หรือไฟล์ gzip'd) กำลังถูกไพพ์ไปยังอินพุตมาตรฐานและจะแยกสมาชิกแรกจากไฟล์เก็บถาวรไปยัง stdout เมื่อ stdin มาจากอุปกรณ์ tty funzip จะถือว่าเป็นกระแสข้อมูลบีบอัด (ไบนารี) และแสดงข้อความช่วยเหลือสั้น ๆ แทน หากมีอาร์กิวเมนต์ไฟล์อินพุตจะถูกอ่านจากไฟล์ที่ระบุแทนจาก stdin

เนื่องจากข้อ จำกัด ในการดึงข้อมูลสมาชิกเดี่ยว funzip มีประโยชน์มากที่สุดเมื่อใช้ร่วมกับโปรแกรมผู้จัดเก็บรองเช่น tar (1) ส่วนต่อไปนี้รวมถึงตัวอย่างที่แสดงการใช้งานนี้ในกรณีของการสำรองข้อมูลดิสก์ลงในเทป

สิ่งนี้สอดคล้องกับแนวคิดที่ว่าคลังเก็บ linux ส่วนใหญ่มักจะมีค่า TAR'ed และจากนั้น ZIPped ในบางวิธี (gzip, bzip, et al) tar.ZIPนี้จะทำงานสำหรับคุณถ้าคุณมี


เป็นที่น่าสังเกตว่าfunzipเขียนโดย Mark Adler ผู้เขียนต้นฉบับ Info-ZIP เขาเขียนในหน้าคน funzip

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

อย่างไรก็ตามจะไม่เห็นการอัปเดตดังกล่าว ฉันสงสัยว่า Mark พบว่าไม่จำเป็นเพราะวิธีการเก็บถาวรอื่น ๆ ทำงานได้อย่างง่ายดายกับ TAR


เพียงความเห็น; บางคนต้องการงูใหญ่หรือภาษาใด ๆ เป็นตัวเลือกในการคลายซิป ตัวอย่างสำคัญคือ Heroku ซึ่งไม่รวม tar หรือ unzip ในระบบ การหลีกเลี่ยงคือการใช้ jar โดยการติดตั้ง Java ที่ได้รับอนุญาต
Nick

มีเพิ่มเติมเกี่ยวกับการจัดการกับข้อ จำกัด ของ funzip และเครื่องมือที่คล้ายกัน (โดยเฉพาะอย่างยิ่งความสามารถในการแสดงสมาชิกคนแรกของการเก็บถาวร) ในคำตอบนี้: unix.stackexchange.com/a/211286/77539
Joshua Goldberg

6

ฉันชอบที่จะใช้ curl เพราะติดตั้งโดยค่าเริ่มต้น ( -Lจำเป็นสำหรับการเปลี่ยนเส้นทางซึ่งมักเกิดขึ้น)

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

อย่างไรก็ตามbsdtarไม่มีการติดตั้งตามค่าเริ่มต้นและฉันไม่funzipสามารถทำงานได้


ยังใช้งานได้ดีกับไฟล์หลาย ๆ ไฟล์
jonnor

5

นี่คือ repost ของคำตอบของฉันสำหรับคำถามที่คล้ายกัน:

รูปแบบไฟล์ ZIP ประกอบด้วยไดเรกทอรี (ดัชนี) ที่ส่วนท้ายของไฟล์เก็บถาวร ไดเรกทอรีนี้จะบอกว่าที่ไหนในไฟล์เก็บถาวรแต่ละไฟล์จะอยู่และทำให้สามารถเข้าถึงแบบสุ่มได้อย่างรวดเร็วโดยไม่ต้องอ่านไฟล์เก็บถาวรทั้งหมด

ดูเหมือนว่าจะมีปัญหาเมื่อพยายามอ่านไฟล์ ZIP ผ่านไปป์โดยที่ดัชนีจะไม่ถูกเข้าถึงจนกว่าจะถึงจุดสิ้นสุดและสมาชิกแต่ละคนจะไม่สามารถแยกไฟล์ได้อย่างถูกต้องจนกว่าจะอ่านไฟล์ทั้งหมดและไม่สามารถใช้งานได้อีกต่อไป . ดังนั้นจึงไม่น่าแปลกใจเลยที่ตัวบีบอัด ZIP ส่วนใหญ่จะล้มเหลวเมื่อทำการจัดเก็บลงสื่อถาวรผ่านไปป์

ไดเรกทอรีที่ส่วนท้ายของไฟล์เก็บถาวรไม่ใช่ตำแหน่งเดียวที่เก็บข้อมูลเมตาไฟล์ในไฟล์เก็บถาวร นอกจากนี้แต่ละรายการยังรวมข้อมูลนี้ไว้ในส่วนหัวของไฟล์ในเครื่องเพื่อการสำรองข้อมูล

แม้ว่าไม่ใช่ตัวบีบอัด ZIP ทุกตัวจะใช้ส่วนหัวของไฟล์ในเครื่องเมื่อดัชนีไม่พร้อมใช้งานหน้า tar และ cpio จะสิ้นสุดลงที่การจัดเก็บถาวร (aka bsdtar และ bsdcpio) สามารถทำได้เมื่ออ่านผ่านไพพ์หมายความว่าเป็นไปได้ดังต่อไปนี้:

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

4

ไม่สามารถทำได้กับ Info-Zip ซึ่งเป็นการนำ OSS มาใช้บ่อยที่สุด ที่สำคัญกว่านั้นไม่แนะนำให้ใช้เนื่องจากโครงสร้างของไฟล์เก็บถาวร ZIP

หากการเปลี่ยนแปลงรูปแบบสามารถใช้งานได้ให้พิจารณาใช้ tar (1) แทน มีความสุขมากกับอินพุต / เอาต์พุตแบบสตรีมและที่จริงแล้วคาดว่าจะเป็นค่าเริ่มต้น

นอกจากนี้คุณมักจะสามารถบอกได้ว่าแอปพลิเคชันคาดว่าสตรีมอินพุต / เอาต์พุตโดยการระบุ "-" สำหรับชื่อไฟล์ Info-Zip อย่างที่คุณจินตนาการได้ว่าจะไม่ถือเป็นอาร์กิวเมนต์ที่ถูกต้อง



3

ยูทิลิตี้ทั่วไปที่ง่ายที่สุดที่มีอยู่ซึ่งจะทำเช่นนี้jarซึ่งจะสันนิษฐานว่า STDIN จะถูกใช้หากคุณผ่านมันไม่มีไฟล์ args นอกจากนี้ยังใช้อาร์กิวเมนต์ที่คล้ายกับtarโปรแกรมสำหรับการดำเนินการ

เช่นรายการเนื้อหาของไฟล์เก็บถาวร

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

ในขณะที่ Java ไม่ได้ติดตั้งไว้เสมอในเครื่องที่เป็นอยู่นั้นjarเป็นวิธีที่สะดวกที่สุดในการทำเช่นนี้


3

โพสต์คำตอบของฉัน :

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แต่นั่นเป็นเพียงซ้ำซ้อนของ

หากคุณใช้ distro BusyBox โดยค่าเริ่มต้น (เช่นอัลไพน์) unzip -วิ่งเพียง


1

ฉันต้องการสิ่งที่ซับซ้อนกว่านี้เล็กน้อย - แยกไฟล์เฉพาะถ้ามีอยู่ ความยากลำบากในการสตรีมไฟล์อินพุตอาจไม่ใช่ไฟล์ซิปและในกรณีนี้ฉันต้องการให้ดำเนินการต่อผ่านไปป์ นี่คือวิธีแก้ปัญหาของฉัน (ขอบคุณมากกับโซลูชันของ 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)"

ฉันบันทึกสิ่งนี้เป็นไฟล์ชื่อ "effpoptp" (ไม่ใช่ชื่อง่ายๆ) ในโฟลเดอร์ "/ bin" บนเครื่องของฉันดังนั้นการทดสอบจึงเป็นเช่นนั้น:

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

จุดประสงค์คือเพื่อควบคุมเวอร์ชันไฟล์ MySQL Workbench โดยที่ไฟล์นั้นอาจเป็นไฟล์ xml ชื่อเป็นไฟล์ workbench หรือไฟล์ workbench ที่สมบูรณ์

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.