ซิปไฟล์ทั้งหมดในไดเรกทอรีหรือไม่


483

มีวิธีซิปไฟล์ทั้งหมดในไดเรกทอรีที่กำหนดด้วยzipคำสั่งหรือไม่? ฉันเคยได้ยินเรื่องการใช้*.*งาน แต่ฉันต้องการให้มันทำงานกับไฟล์ที่ไม่มีนามสกุลได้เช่นกัน


2
คุณเคยลองการนำทางขึ้นหนึ่งระดับจากไดเรกทอรีที่คุณต้องการแล้วทำzip myarch.zip mydir/*หรือไม่?
โจเซฟอาร์

13
หรือดีกว่าzip -r myarch.zip mydir/*
Adam

25
หรือดีกว่าzip -r myarch.zip mydir
ctrl-alt-delor

*.*หมายถึงไฟล์ใด ๆ ที่มีจุด ใน cp / m และ dos ไฟล์ทั้งหมดมีจุดและทำให้คุณพิมพ์ (ไม่สามารถทำได้*) ดังนั้นคนมาดู*.*ไฟล์ทั้งหมด ในที่สุด Microsoft ได้เพิ่มชื่อไฟล์แบบยาวที่อาจมีจุดศูนย์หรือมากกว่านั้น เพื่อค้นหาไฟล์ที่มีจุดบน windows *.*.*คุณต้องพิมพ์เป็น
ctrl-alt-delor

คำตอบ:


705

คุณสามารถใช้*; *.*ไม่มีความจำเป็นในการ นามสกุลไฟล์ไม่ได้เป็นพิเศษใน Unix *ตรงกับศูนย์หรือมากกว่าตัวอักษรรวมถึงจุด ดังนั้นจึงตรงกับfoo.pngเพราะเป็นศูนย์หรือมากกว่าตัวละคร (เจ็ดจะแน่นอน)

โปรดทราบว่า*โดยค่าเริ่มต้นจะไม่ตรงกับไฟล์ที่ขึ้นต้นด้วยจุด (ไม่รวม*.*) นี่คือสิ่งที่คุณต้องการบ่อยครั้ง หากไม่ใช่ในกรณีทุบตีหากคุณshopt -s dotglobต้องการ (แต่จะยังคงไม่รวม.และ..) กระสุนอื่น ๆ มีวิธีที่แตกต่างกัน (หรือไม่มีเลย) รวมถึง dotfiles

หรืออีกทางหนึ่งzipนอกจากนี้ยังมี-r(recursive) ตัวเลือกที่จะทำต้นไม้ไดเรกทอรีทั้งหมดในครั้งเดียว (และไม่ต้องกังวลเกี่ยวกับปัญหา dotfile) ที่:

zip -r myfiles.zip mydir

ที่mydirอยู่ในไดเรกทอรีที่มีไฟล์ของคุณ โปรดทราบว่ารหัสไปรษณีย์ที่ผลิตจะมีโครงสร้างไดเรกทอรีรวมถึงไฟล์ ตามที่ peterph ชี้ให้เห็นในความคิดเห็นของเขาสิ่งนี้มักจะถูกมองว่าเป็นสิ่งที่ดี: การคลายซิปจะจัดเก็บไฟล์ที่ถูกแยกทั้งหมดไว้อย่างเรียบร้อยในไดเรกทอรีย่อยเดียว

คุณยังสามารถบอกให้ zip ไม่เก็บเส้นทางด้วยตัวเลือก-j/--junk-paths

zipคำสั่งมาพร้อมกับเอกสารบอกคุณเกี่ยวกับทุก (มาก) ตัวเลือกของตน พิมพ์man zipเพื่อดูเอกสารประกอบนั้น นี่ไม่ใช่ซิปที่ไม่ซ้ำกัน คุณสามารถรับเอกสารสำหรับคำสั่งส่วนใหญ่ด้วยวิธีนี้


9
คุณอาจต้องการเพิ่มถือว่าเป็นแนวปฏิบัติที่ดีที่จะมีทุกอย่างในไฟล์เก็บถาวรในไดเรกทอรีระดับบนสุดเพื่อที่ว่าจะไม่สร้างความเสียหายให้กับไดเรกทอรีปัจจุบันของเขา / เธอในการแยก
เตอร์

@ peterph เสร็จแล้ว แม้ว่านี่จะเป็นการประชุมน้อยกว่าในไฟล์ zip มากกว่าในเช่น tarfile ฉันกลัว
derobert

น่าเสียดายใช่ อาจเป็นเพราะ windows 'ลาก' n'drop ลงบนเดสก์ท็อปและ linux ซึ่งเป็นมรดกของการทำงานกับซอร์สโค้ด
เตอร์

2
โปรดทราบว่า*shell-globbing ไม่รวม dotfiles (เช่นชื่อไฟล์ที่ขึ้นต้นด้วย.) นี่เป็นข้อได้เปรียบอีกอย่างหนึ่งในการซิปไดเรกทอรีทั้งหมดด้วยชื่อ
mrb

แต่การใช้ -r นั้นรวมถึงไดเรกทอรีเองซึ่งทำให้สิ่งที่ฉันทำพังลงไป * จะไม่รวม.และ..?
tkbx

11

ในกรณีของฉันฉันต้องการซิปไฟล์แต่ละไฟล์ลงในไฟล์เก็บถาวรของตัวเองดังนั้นฉันจึงทำสิ่งต่อไปนี้ (เป็นzsh):

$ for file in *; do zip ${file%.*}.zip $file; done

1
ไม่มีmkvที่นี่? ยังไม่มีอะไรที่นี่เป็นพิเศษ - zshเฉพาะ คุณจะต้องการอ้างอิงตัวแปรที่มีชื่อไฟล์อย่างถูกต้องดังนั้นzip "${file%.*}.zip" "$file"ด้วยเครื่องหมายคำพูดคู่รอบตัวแปรทั้งสอง
tripleee

1
@tripleee mkvประการแรกขอขอบคุณสำหรับการชี้ให้เห็นการอ้างอิงที่ผิดพลาดของฉันไป ประการที่สองคือการอ้างข้อโต้แย้งที่ไม่จำเป็นในซึ่งแตกต่างจากในzsh นั่นเป็นเหตุผลที่ผมระบุว่านี่เป็นคำสั่งสำหรับbash zsh
Radon Rosborough

การแทนที่เซมิโคลอนสุดท้ายด้วยเครื่องหมายและอาจเพิ่มความเร็วขึ้นอย่างมาก (หากจำนวนไฟล์ในไดเรกทอรีเหมาะสม ... ) มิฉะนั้นfind . -type f -maxdepth 1 -print0|xargs -r0 -n1 -P64 -I{} bash -c 'f="{}"; zip "${f%.*}.zip" "$f"'(พร้อม-Pปรับขึ้นอยู่กับเธรด CPU ของคุณ ... ) (การพึ่งพา GNU จำนวนมาก ... )
Gert van den Berg

5

อีกวิธีหนึ่งคือใช้ find และ xargs: (ซึ่งอาจรวมถึงไดเร็กตอรี่ "." ใน zip, แต่มันควรจะทำการแตกไฟล์ได้อย่างถูกต้องด้วยการทดสอบของฉัน, zip จะตัดจุดก่อนการบีบอัด) find . -type f -exec zip zipfile.zip {} +

( +สามารถแทนที่ด้วย\;หากเวอร์ชันของคุณfindไม่รองรับการ+สิ้นสุดสำหรับ exec มันจะช้ากว่าแม้ว่า ... )

โดยค่าเริ่มต้นนี้จะรวมไดเรกทอรีย่อยทั้งหมด ใน GNU find -maxdepthสามารถป้องกันได้


(ซึ่งแตกต่างจากการแก้ปัญหาโดยใช้*นี้จะรวมถึง dotfiles และจะไม่ตกไปถ้ามีไฟล์มากเกินไปในไดเรกทอรี)
Gert van den Berg

1

อีกวิธีหนึ่ง (ช้า) ในการทำเช่นนี้ (ซึ่งเพิ่มไฟล์หนึ่งไฟล์ลงในไฟล์ zip ในเวลาเดียวกัน):

for f in * .[^.]*; do
    [ -r "$f" ] || continue # Skip directories or non-existant files (Probably ".[^.]*" if directory has no dotfiles). Using -e will allow directories to be used as well
    zip zipfile.zip "$f" # If directories are included, you probably want to add -r
done

นี่เป็นปัญหา dotfile ของ*(เพิ่มวิธีแก้ไข) และจะเริ่ม zip หนึ่งครั้งสำหรับแต่ละไฟล์เพิ่มไปยังไฟล์เก็บถาวร ในbashมันจะจัดการกับไฟล์จำนวนมาก

มันจะช้ากว่าวิธีอื่น ๆ ส่วนใหญ่ แต่ค่อนข้างง่าย


1
ฉันจะบอกว่านี่ง่ายกว่าคำตอบที่ยอมรับและช้าลงซึ่งจะถามคำถามว่า: "ทำไมทุกคนจะทำเช่นนี้" หากคุณสามารถตอบคำถามนั้นได้ฉันขอแนะนำให้คุณใส่บริบทนั้นในคำตอบของคุณมิฉะนั้นฉันคิดว่ามันเป็นคำตอบที่ไม่ดีสำหรับคำถามเก่าที่มีคำตอบที่ดีอยู่แล้ว
Centimane

@Centimane: ฉันสังเกตเห็นข้อ จำกัด ฉันรู้สึกว่านี่มีคุณค่าทางการศึกษา (ถ้าไม่ข้ามไดเรกทอรีมันค่อนข้างง่าย) หากคุณต้องการคำตอบที่รวดเร็วยิ่งขึ้นโดยใช้ (มาตรฐาน) เครื่องมือภายนอกแทนอื่น ๆ ของฉันคำตอบที่ครอบคลุมว่า (ด้วยการจัดการ dotfiles ลบออก (ซึ่งส่งผลกระทบต่อความถูกต้องโดยไม่ได้กล่าวถึงในคำถาม) ฉันรู้สึกว่ามันค่อนข้างหรูหรา):for f in *; do zip zip.zip "$f"; done
Gert van den Berg

1
โปรดทราบว่าคำตอบที่ยอมรับไม่ได้ใช้คำสั่งภายนอกและจะเร็วขึ้น คำตอบนี้จะเป็นประโยชน์ในสถานการณ์ใด
Centimane

@Centimane ด้วย tar เมื่อมีไฟล์มากกว่าสิ่งที่ bash สามารถส่งผ่านเป็นพารามิเตอร์ได้ (ค้นหา + xargs ดีกว่าเพราะลูปง่ายกว่า ... ) มันเป็นคำตอบ (เฉพาะ) สำหรับคำถาม แน่นอนว่าไม่ใช่คำตอบที่ดีที่สุด (คำตอบที่ไม่เหมาะสมอาจยังมีประโยชน์สำหรับปัญหาที่คล้ายกันหากมีคนมีสถานการณ์ที่แตกต่างออกไปเล็กน้อย - เช่นต้องการ tar ไฟล์ไดเรกทอรีใด ๆ ในนั้น)
Gert van den Berg
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.