Anda bisa menggunakan globstar.
Dengan globstaropsi shell diaktifkan, yang Anda butuhkan adalah gzip -vk **/*.{css,html}.
Bash shell memiliki globstaropsi yang memungkinkan Anda menulis rekursif gumpalan dengan **. shopt -s globstarmemungkinkannya. Tapi Anda mungkin tidak ingin melakukan itu untuk perintah lain yang Anda jalankan nanti, jadi Anda bisa menjalankannya dan gzip perintah Anda dalam subkulit sebagai gantinya.
Perintah ini gzips semua .cssdan .htmlfile dalam direktori saat ini salah satu subdirektorinya, salah mereka subdirektori, dll, menjaga file asli ( -k) dan memberitahu Anda apa yang dilakukannya ( -v):
(shopt -s globstar; gzip -vk **/*.{css,html})
Jika Anda ingin mencocokkan nama file dengan case-insensitive sehingga ekstensi dengan beberapa atau semua huruf besar disertakan, maka Anda juga dapat mengaktifkan nocaseglobopsi shell:
(shopt -s globstar nocaseglob; gzip -vk **/*.{css,html})
;memisahkan dua perintah, dan bagian luar ( )menyebabkannya dijalankan dalam subkulit. Mengatur opsi shell di subkulit tidak menyebabkannya diatur dalam shell panggilan. Jika Anda tidak ingin mengaktifkan globstarmaka Anda dapat menjalankan shopt -s globstar; maka Anda bisa menjalankan perintah:
gzip -vk **/*.{css,html}
Anda dapat menonaktifkan globstardengan shopt -u globstar. Anda dapat memeriksa apakah saat ini diaktifkan dengan shopt globstar.
Bagaimana itu bekerja
Kunci untuk bagaimana gzipperintah ini bekerja adalah bahwa shell melakukan ekspansi di atasnya untuk menghasilkan daftar setiap file dalam hierarki direktori dengan nama yang cocok, kemudian melewati masing-masing nama file ini sebagai argumen gzip.
- Ekspansi brace berubah
**/*.{css,html}menjadi **/*.css **/*.html.
- Kemudian globbing memperluas kedua pola menjadi nama-nama file yang dapat diakses di bawah direktori saat ini (
**, karena globstar) yang nama filenya terdiri dari apa saja ( *) diikuti oleh akhiran yang ditentukan ( .cssatau .htmldalam kasus ini).
Ini tidak cocok dengan file yang namanya dimulai dengan. atau yang berada di direktori bernama cara ini. Anda mungkin tidak memiliki file HTML dan CSS tersebut dan, jika Anda melakukannya, Anda mungkin tidak ingin memasukkannya. Tetapi jika Anda ingin memasukkannya, maka Anda dapat mencocokkannya secara eksplisit tergantung pada kebutuhan Anda. Misalnya, mengubah **/*.{css,html}ke **/{,.}*.{css,html}termasuk file yang dimulai dengan .saat masih belum mencari di folder yang melakukan.
Jika Anda ingin kedua file yang namanya mulai .dan file dalam direktori yang namanya mulai .dimasukkan, ada cara yang lebih bersih dan sederhana: aktifkan dotglobopsi shell.
(shopt -s globstar dotglob; gzip -vk **/*.{css,html})
Atau jika Anda ingin pencocokan huruf besar-kecil dan pencocokan nama file yang dimulai dengan .:
(shopt -s globstar nocaseglob dotglob; gzip -vk **/*.{css,html})
Mungkin saja, meskipun sangat jarang, untuk **memperluas ke sesuatu yang terlalu lama.
Jika Anda memiliki sejumlah besar file bernama cara ini, maka ini mungkin gagal dengan pesan kesalahan yang menjelaskan bahwa shell tidak dapat membangun baris perintah karena itu akan terlalu lama. (Bahkan dengan ribuan file, ini biasanya tidak masalah.)
gzip tidak akan dipanggil sama sekali, sehingga Anda tidak akan mendapatkan pekerjaan setengah jadi.
Jika kesalahan ini terjadi, atau jika Anda khawatir tentang hal itu, Anda dapat menggunakannya finddengan -exec, seperti yang dijelaskan steeldriver (dengan {} \;) atau seperti yang saya jelaskan di bawah (dengan {} +).
Anda dapat menggunakannya finddengan -execaksi dan +untuk efisiensi.
The gzipmendukung perintah yang diberikan nama-nama beberapa file yang akan dikompresi. Tetapi findperintah ini , meskipun bekerja dengan baik dan tidak akan lambat kecuali jika Anda memiliki banyak file, jalankan gzipperintah sekali untuk setiap file:
find . \( -name \*.css -o -name \*.html \) -exec gzip -vk {} \;
Ini berfungsi, dan Anda pasti bisa menggunakannya. ( .mencari dari direktori saat ini. Selain itu, ini benar-benar cara menulis perintah dalam jawaban steeldriver yang sangat bagus ; Anda dapat menggunakan gaya apa pun yang Anda inginkan.)
Anda juga dapat membuat findbeberapa nama file lewat gzipdan menjalankannya hanya sebanyak yang diperlukan - yang hampir selalu hanya sekali. Untuk melakukannya, gunakan +sebagai ganti\; . The +Argumen harus datang hanya setelah {}. findganti +dengan nama file tambahan, jika ada.
find . \( -name \*.css -o -name \*.html \) -exec gzip -vk {} +
Tidak masalah untuk menggunakan +bahkan jika hanya ada beberapa file yang cocok, dan ketika ada banyak dari mereka, itu bisa terasa lebih cepat daripada memiliki gzipdoa terpisah untuk setiap file.
Seperti disebutkan steeldriver , Anda dapat menggunakan -inamealih-alih -namemencocokkan file yang namanya suka .cssatau .htmltetapi dengan huruf besar berbeda. Ini sesuai dengan mengaktifkan nocaseglobdalam globstarmetode berbasis yang dijelaskan di atas.
Terakhir, Anda mungkin tidak memiliki file atau direktori yang cocok dengan yang dimulai .. Tetapi jika Anda melakukannya, findsecara otomatis memasukkan mereka. Jika Anda ingin mengecualikan mereka (seperti yang terjadi pada globstarmetode -based yang dijelaskan di atas ketika dotglobdimatikan), Anda dapat :
find . -not -path '*/.*' \( -name \*.css -o -name \*.html \) -exec gzip -vk {} +
Cara globstarberbasis-yang dijelaskan di atas lebih mudah untuk ditulis, terutama jika Anda mengecualikan direktori dan file yang dimulai dengan ., karena itulah defaultnya.
Apa yang tidak boleh dilakukan ...
Nama file dapat berisi karakter apa pun kecuali pemisah jalur /dan karakter nol . Ada banyak teknik yang merusak nama file aneh, dan mereka biasanya lebih rumit daripada teknik yang selalu berhasil. Jadi saya sarankan menghindari mereka bahkan ketika Anda tahu (atau berpikir Anda tahu) mereka baik-baik saja dalam situasi spesifik Anda. Dan tentu saja Anda tidak boleh menggunakannya jika Anda mungkin memiliki nama file dengan karakter yang dapat diperlakukan secara khusus, termasuk spasi.
Dimungkinkan untuk mem-pipe output dengan aman findke perintah lain yang memprosesnya jika Anda menggunakan -print0atau tindakan serupa untuk menyebabkannya menempatkan karakter nol di antara path sebagai ganti baris baru , dan bukan sebaliknya. Nama file dapat berisi baris baru (meskipun saya tidak menyarankan Anda untuk memberi nama file dengan sengaja). Sebuah findperintah dengan -printtindakan - termasuk perintah find dengan tidak ada tindakan eksplisit, sejak itu -printadalah default - tidak menghasilkan output yang aman dapat disalurkan atau diberikan kepada perintah lain yang melakukan tindakan pada file.
Output yang finddihasilkan dengan -print0action dapat dengan aman disalurkan ke xargs -0( -0flag memberitahu xargsuntuk mengharapkan input yang dipisahkan nol).
-rberfungsi seperti yang dirancang. Dari man gzip : Jelajahi struktur direktori secara rekursif. Jika salah satu nama file yang ditentukan pada baris perintah adalah direktori , gzip akan turun ke direktori dan kompres semua file yang ditemukannya di sana (atau dekompres mereka dalam kasus gunzip). (penekanan pada saya)