ฉันสามารถทำให้ unzip หรือโปรแกรมที่คล้ายกันทำงานบนเอาต์พุตมาตรฐานได้หรือไม่ สถานการณ์คือฉันกำลังดาวน์โหลดไฟล์ zip ซึ่งควรจะคลายซิปทันที
ปัญหาที่เกี่ยวข้อง: ฉันจะไพพ์ไฟล์ที่ดาวน์โหลดไปยังเอาต์พุตมาตรฐานใน bash ได้อย่างไร
ฉันสามารถทำให้ unzip หรือโปรแกรมที่คล้ายกันทำงานบนเอาต์พุตมาตรฐานได้หรือไม่ สถานการณ์คือฉันกำลังดาวน์โหลดไฟล์ zip ซึ่งควรจะคลายซิปทันที
ปัญหาที่เกี่ยวข้อง: ฉันจะไพพ์ไฟล์ที่ดาวน์โหลดไปยังเอาต์พุตมาตรฐานใน bash ได้อย่างไร
คำตอบ:
ในขณะที่ไฟล์ 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
.read()
วิธีการ
สิ่งนี้ไม่น่าเป็นไปได้ตามที่คุณคาดหวัง Zip ไม่ได้เป็นเพียงรูปแบบการบีบอัดเท่านั้น แต่ยังเป็นรูปแบบคอนเทนเนอร์ด้วย มันรวมงานของ tar และ gzip.bzip2 ไว้ในที่เดียว ต้องบอกว่าหากไฟล์ zip ของคุณมีไฟล์เดียวคุณสามารถใช้ unzip -p เพื่อแตกไฟล์ไปยัง stdout หากคุณมีมากกว่าหนึ่งไฟล์คุณไม่สามารถบอกได้ว่าจะเริ่มและหยุดที่ใด
สำหรับการอ่านจาก stdin หน้า unzip man มีประโยคนี้:
ไฟล์เก็บถาวรที่อ่านจากอินพุตมาตรฐานยังไม่ได้รับการสนับสนุนยกเว้นด้วย funzip (และจากนั้นเฉพาะสมาชิกแรกของไฟล์เก็บถาวรที่สามารถแตกได้)
คุณอาจมีโชคกับ funzip
สิ่งที่คุณต้องการทำคือให้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
ฉันชอบที่จะใช้ curl เพราะติดตั้งโดยค่าเริ่มต้น ( -L
จำเป็นสำหรับการเปลี่ยนเส้นทางซึ่งมักเกิดขึ้น)
curl -L http://example.com/file.zip | bsdtar -xvf - -C /path/to/directory/
อย่างไรก็ตามbsdtar
ไม่มีการติดตั้งตามค่าเริ่มต้นและฉันไม่funzip
สามารถทำงานได้
นี่คือ repost ของคำตอบของฉันสำหรับคำถามที่คล้ายกัน:
รูปแบบไฟล์ ZIP ประกอบด้วยไดเรกทอรี (ดัชนี) ที่ส่วนท้ายของไฟล์เก็บถาวร ไดเรกทอรีนี้จะบอกว่าที่ไหนในไฟล์เก็บถาวรแต่ละไฟล์จะอยู่และทำให้สามารถเข้าถึงแบบสุ่มได้อย่างรวดเร็วโดยไม่ต้องอ่านไฟล์เก็บถาวรทั้งหมด
ดูเหมือนว่าจะมีปัญหาเมื่อพยายามอ่านไฟล์ ZIP ผ่านไปป์โดยที่ดัชนีจะไม่ถูกเข้าถึงจนกว่าจะถึงจุดสิ้นสุดและสมาชิกแต่ละคนจะไม่สามารถแยกไฟล์ได้อย่างถูกต้องจนกว่าจะอ่านไฟล์ทั้งหมดและไม่สามารถใช้งานได้อีกต่อไป . ดังนั้นจึงไม่น่าแปลกใจเลยที่ตัวบีบอัด ZIP ส่วนใหญ่จะล้มเหลวเมื่อทำการจัดเก็บลงสื่อถาวรผ่านไปป์
ไดเรกทอรีที่ส่วนท้ายของไฟล์เก็บถาวรไม่ใช่ตำแหน่งเดียวที่เก็บข้อมูลเมตาไฟล์ในไฟล์เก็บถาวร นอกจากนี้แต่ละรายการยังรวมข้อมูลนี้ไว้ในส่วนหัวของไฟล์ในเครื่องเพื่อการสำรองข้อมูล
แม้ว่าไม่ใช่ตัวบีบอัด ZIP ทุกตัวจะใช้ส่วนหัวของไฟล์ในเครื่องเมื่อดัชนีไม่พร้อมใช้งานหน้า tar และ cpio จะสิ้นสุดลงที่การจัดเก็บถาวร (aka bsdtar และ bsdcpio) สามารถทำได้เมื่ออ่านผ่านไพพ์หมายความว่าเป็นไปได้ดังต่อไปนี้:
wget -qO- http://example.org/file.zip | bsdtar -xvf-
ไม่สามารถทำได้กับ Info-Zip ซึ่งเป็นการนำ OSS มาใช้บ่อยที่สุด ที่สำคัญกว่านั้นไม่แนะนำให้ใช้เนื่องจากโครงสร้างของไฟล์เก็บถาวร ZIP
หากการเปลี่ยนแปลงรูปแบบสามารถใช้งานได้ให้พิจารณาใช้ tar (1) แทน มีความสุขมากกับอินพุต / เอาต์พุตแบบสตรีมและที่จริงแล้วคาดว่าจะเป็นค่าเริ่มต้น
นอกจากนี้คุณมักจะสามารถบอกได้ว่าแอปพลิเคชันคาดว่าสตรีมอินพุต / เอาต์พุตโดยการระบุ "-" สำหรับชื่อไฟล์ Info-Zip อย่างที่คุณจินตนาการได้ว่าจะไม่ถือเป็นอาร์กิวเมนต์ที่ถูกต้อง
ใน zsh คุณสามารถทำสิ่งต่อไปนี้:
unzip =( curl http://example.com/someZipFile.zip )
ยูทิลิตี้ทั่วไปที่ง่ายที่สุดที่มีอยู่ซึ่งจะทำเช่นนี้jar
ซึ่งจะสันนิษฐานว่า STDIN จะถูกใช้หากคุณผ่านมันไม่มีไฟล์ args นอกจากนี้ยังใช้อาร์กิวเมนต์ที่คล้ายกับtar
โปรแกรมสำหรับการดำเนินการ
เช่นรายการเนื้อหาของไฟล์เก็บถาวร
curl https://my.example.com/file.zip | jar t
ในขณะที่ Java ไม่ได้ติดตั้งไว้เสมอในเครื่องที่เป็นอยู่นั้นjar
เป็นวิธีที่สะดวกที่สุดในการทำเช่นนี้
โพสต์คำตอบของฉัน :
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 -
วิ่งเพียง
ฉันต้องการสิ่งที่ซับซ้อนกว่านี้เล็กน้อย - แยกไฟล์เฉพาะถ้ามีอยู่ ความยากลำบากในการสตรีมไฟล์อินพุตอาจไม่ใช่ไฟล์ซิปและในกรณีนี้ฉันต้องการให้ดำเนินการต่อผ่านไปป์ นี่คือวิธีแก้ปัญหาของฉัน (ขอบคุณมากกับโซลูชันของ 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 ที่สมบูรณ์