คุณสามารถใช้ globstar
ด้วยตัวเลือกเปลือกเปิดใช้งานทั้งหมดที่คุณต้องการglobstar
gzip -vk **/*.{css,html}
ทุบตีเปลือกมีglobstar
ตัวเลือกที่ช่วยให้คุณเขียน recursive globs**
กับ shopt -s globstar
เปิดใช้งานมัน แต่คุณอาจไม่ต้องการทำเช่นนั้นสำหรับคำสั่งอื่น ๆ ที่คุณเรียกใช้ในภายหลังเพื่อให้คุณสามารถเรียกใช้และgzip
คำสั่งของคุณในsubshellแทน
คำสั่งนี้gzip
ทุกอย่าง.css
และ.html
ไฟล์ในไดเรกทอรีปัจจุบันใด ๆ ของไดเรกทอรีย่อยใด ๆ ของพวกเขาไดเรกทอรีย่อย ฯลฯ , การเก็บรักษาไฟล์ต้นฉบับ ( -k
) และบอกคุณว่ามันทำ ( -v
):
(shopt -s globstar; gzip -vk **/*.{css,html})
หากคุณต้องการจับคู่ชื่อไฟล์แบบตรงตามตัวพิมพ์ใหญ่เพื่อให้ส่วนขยายเหล่านั้นรวมตัวอักษรบางส่วนหรือทั้งหมดเป็นตัวพิมพ์ใหญ่คุณสามารถเปิดใช้งานnocaseglob
ตัวเลือกเชลล์ได้:
(shopt -s globstar nocaseglob; gzip -vk **/*.{css,html})
;
แยกคำสั่งสองคำสั่งและ(
)
สาเหตุด้านนอกทำให้คำสั่งเหล่านั้นถูกเรียกใช้ใน subshell การตั้งค่าตัวเลือกของเชลล์ใน subshell ไม่ได้ทำให้มันถูกตั้งค่าในการเรียกเชลล์ หากคุณไม่ต้องการเปิดใช้งานglobstar
แล้วคุณสามารถเรียกใช้shopt -s globstar
; จากนั้นคุณสามารถเรียกใช้คำสั่ง:
gzip -vk **/*.{css,html}
คุณสามารถปิดการใช้งานด้วยglobstar
คุณสามารถตรวจสอบได้หากมีการเปิดใช้งานอยู่ด้วยshopt -u globstar
shopt globstar
มันทำงานอย่างไร
กุญแจสำคัญในการวิธีนี้ทำงานคำสั่งว่าการขยายเปลือกดำเนินการเกี่ยวกับมันในการผลิตรายการของแต่ละไฟล์ในลำดับชั้นไดเรกทอรีที่มีชื่อตรงกันแล้วผ่านไปแต่ละชื่อไฟล์เหล่านี้เป็นข้อโต้แย้งgzip
gzip
- การขยายตัวรั้งผลัดกันเข้าไป
**/*.{css,html}
**/*.css **/*.html
- จากนั้นglobbingขยายทั้งสองรูปแบบเข้ามาในชื่อของไฟล์ที่สามารถเข้าถึงได้ภายใต้ไดเรกทอรีปัจจุบัน (
**
เนื่องจากglobstar
) ที่มีชื่อไฟล์ประกอบด้วยอะไร ( *
) ตามด้วยคำต่อท้ายที่ระบุ ( .css
หรือ.html
ในกรณีนี้)
สิ่งนี้ไม่ตรงกับไฟล์ที่ชื่อขึ้นต้นด้วย.
หรืออยู่ในไดเรกทอรีที่ตั้งชื่อด้วยวิธีนี้ คุณอาจไม่มีไฟล์ HTML และ CSS และคุณอาจไม่ต้องการรวมไฟล์เหล่านั้น แต่ถ้าคุณต้องการที่จะรวมพวกเขาคุณสามารถจับคู่พวกเขาอย่างชัดเจนขึ้นอยู่กับความต้องการของคุณ ตัวอย่างเช่นการเปลี่ยน**/*.{css,html}
เป็น**/{,.}*.{css,html}
ไฟล์ที่ขึ้นต้นด้วย.
ในขณะที่ยังไม่ค้นหาในโฟลเดอร์ที่ทำ
หากคุณต้องการให้ทั้งไฟล์ที่ชื่อขึ้นต้นด้วย.
และไฟล์ในไดเรกทอรีที่ชื่อขึ้นต้น.
รวมอยู่นั้นจะมีวิธีที่สะอาดกว่าและง่ายกว่า: เปิดใช้งานdotglob
ตัวเลือกเชลล์
(shopt -s globstar dotglob; gzip -vk **/*.{css,html})
หรือถ้าคุณต้องการที่ตรงกันกรณีตายและการจับคู่ของชื่อไฟล์ที่ขึ้นต้นด้วย.
:
(shopt -s globstar nocaseglob dotglob; gzip -vk **/*.{css,html})
เป็นไปได้แม้ว่าจะหายากมากสำหรับ**
การขยายไปยังบางสิ่งที่ยาวเกินไป
หากคุณมีขนาดใหญ่จำนวนไฟล์ชื่อด้วยวิธีนี้แล้วนี้อาจล้มเหลวด้วยข้อผิดพลาดอธิบายว่าเปลือกไม่สามารถสร้างบรรทัดคำสั่งเพราะมันจะยาวเกินไป (ถึงแม้จะมีหลายพันไฟล์นี้มักจะไม่เป็นปัญหา.)
gzip
จะไม่ถูกเรียกเลยดังนั้นคุณจะไม่ได้งานที่ทำไปแล้ว
หากข้อผิดพลาดนี้เกิดขึ้นหรือถ้าคุณกังวลเกี่ยวกับเรื่องนี้คุณสามารถใช้find
กับ-exec
ได้เช่นกันขณะที่steeldriver อธิบาย (ด้วย{} \;
) หรือตามที่ฉันอธิบายด้านล่าง (กับ{} +
)
คุณสามารถใช้find
กับ-exec
แอ็คชั่นและ+
เพื่อประสิทธิภาพ
gzip
ชื่อคำสั่งที่ได้รับการสนับสนุนจากหลายไฟล์ที่ถูกบีบอัด แต่find
คำสั่งนี้แม้ว่ามันจะทำงานได้ดีและจะไม่ช้าถ้าคุณมีไฟล์จำนวนมากให้รันgzip
คำสั่งหนึ่งครั้งสำหรับแต่ละ ไฟล์:
find . \( -name \*.css -o -name \*.html \) -exec gzip -vk {} \;
ใช้งานได้และคุณสามารถใช้งานได้อย่างแน่นอน ( .
ค้นหาจากไดเรกทอรีปัจจุบันนอกจากนั้นมันเป็นวิธีที่แตกต่างกันเล็กน้อยในการเขียนคำสั่งในคำตอบที่ดีมากของ steeldriverคุณสามารถใช้รูปแบบใดก็ได้ที่คุณต้องการ)
นอกจากนี้คุณยังสามารถfind
ส่งผ่านชื่อไฟล์หลาย ๆ ไฟล์ไปยังgzip
และเรียกใช้ได้หลายครั้งเท่าที่จำเป็นซึ่งเกือบจะแค่ครั้งเดียว จะทำอย่างไรที่จะใช้+
\;
แทน อาร์กิวเมนต์ควรมาหลัง+
แทนที่ด้วยชื่อไฟล์เพิ่มเติมถ้ามี{}
find
+
find . \( -name \*.css -o -name \*.html \) -exec gzip -vk {} +
เป็นการดีที่จะใช้+
แม้ว่าจะมีไฟล์ที่ตรงกันเพียงไม่กี่ไฟล์เท่านั้นและเมื่อมีไฟล์จำนวนมากมันก็สามารถสังเกตได้เร็วกว่าการgzip
เรียกใช้ไฟล์แยกต่างหากสำหรับแต่ละไฟล์
ในฐานะที่เป็นคนขับรถเหล็กที่กล่าวถึงคุณสามารถใช้-iname
แทน-name
การจับคู่ไฟล์ที่มีชื่อเหมือน.css
หรือ.html
ด้วยตัวพิมพ์ใหญ่ที่แตกต่างกัน สิ่งนี้สอดคล้องกับการเปิดใช้งานnocaseglob
ในglobstar
วิธี -based อธิบายไว้ข้างต้น
สุดท้ายคุณอาจไม่ได้ตรงกับไฟล์หรือไดเรกทอรีใด ๆ .
ที่เริ่มต้นด้วย แต่ถ้าคุณfind
รวมไว้โดยอัตโนมัติ หากคุณต้องการยกเว้นพวกเขา (เช่นเดียวกับที่เกิดขึ้นกับglobstar
วิธีการตามรายละเอียดด้านบนเมื่อdotglob
ปิด) คุณสามารถ :
find . -not -path '*/.*' \( -name \*.css -o -name \*.html \) -exec gzip -vk {} +
globstar
วิธีชั่อธิบายไว้ข้างต้นคือง่ายต่อการเขียนโดยเฉพาะอย่างยิ่งถ้าคุณไม่รวมไดเรกทอรีและไฟล์ที่ขึ้นต้นด้วย.
ตั้งแต่ที่เริ่มต้น
อะไรไม่ได้ที่จะทำ ...
ชื่อไฟล์สามารถมีตัวอักษรใด ๆ ยกเว้นคั่นเส้นทาง/
และอักขระ null มีเทคนิคมากมายที่ใช้ชื่อไฟล์แปลก ๆ และมักจะซับซ้อนกว่าเทคนิคที่ใช้งานได้ ดังนั้นฉันขอแนะนำให้หลีกเลี่ยงแม้ว่าคุณจะรู้ (หรือคิดว่าคุณรู้) พวกเขาก็โอเคในสถานการณ์เฉพาะของคุณ และแน่นอนคุณจะต้องไม่ใช้มันหากคุณมีชื่อไฟล์ที่มีตัวละครที่อาจได้รับการดูแลเป็นพิเศษรวมถึงช่องว่าง
เป็นไปได้ที่จะไพพ์เอาต์พุตอย่างปลอดภัยfind
ไปยังคำสั่งอื่นที่ประมวลผลหากคุณใช้-print0
หรือการดำเนินการที่คล้ายกันเพื่อทำให้อักขระว่างระหว่างพา ธ แทนการขึ้นบรรทัดใหม่ไม่ใช่อย่างอื่น ชื่อไฟล์สามารถมีการขึ้นบรรทัดใหม่ (แม้ว่าฉันจะไม่สนับสนุนให้คุณตั้งชื่อไฟล์โดยเจตนา) find
คำสั่งด้วย-print
การกระทำ - รวมทั้งคำสั่งพบกับไม่มีการดำเนินการอย่างชัดเจนตั้งแต่นั้นมา-print
เป็นค่าเริ่มต้น - ไม่ได้ผลิตออกที่สามารถได้อย่างปลอดภัยได้รับการประปาหรือให้กับคำสั่งอื่นอย่างอื่นที่มีประสิทธิภาพการดำเนินการในแฟ้ม
เอาต์พุตที่find
สร้างขึ้นพร้อมกับ-print0
แอ็คชันอาจถูกไพพ์อย่างปลอดภัยxargs -0
( -0
แฟล็กบอกxargs
ให้คาดหวังอินพุตที่คั่นด้วย null)
-r
ทำงานตามที่ออกแบบไว้ จากman gzip : เดินทางโครงสร้างไดเร็คทอรี่แบบเรียกซ้ำ หากชื่อไฟล์ใด ๆ ที่ระบุในบรรทัดคำสั่งเป็นไดเรกทอรี gzip จะลงไปในไดเรกทอรีและบีบอัดไฟล์ทั้งหมดที่พบมี (หรือขยายในกรณีของ gunzip) (เน้นที่เหมือง)