Saya mencoba gzip semua file di ubuntu yang memiliki ekstensi file .css, .html atau .js. dalam direktori teratas dan semua subdirektori. Saya ingin menyimpan file asli dan menimpa file .gz, jika sudah ada.
Jadi ketika saya memiliki file n, saya ingin menyimpan file n ini dan membuat file arsip n tambahan. Bukan hanya satu.
Percobaan saya adalah menjalankan skrip yang terlihat seperti ini:
gzip -rkf *.css
gzip -rkf *.html
... one line for each file extension
Pertama: Saya perlu memiliki satu baris di skrip itu untuk setiap ekstensi file yang ingin saya gzip. Tidak apa-apa, tapi saya berharap menemukan cara yang lebih baik
Kedua dan yang lebih penting: Tidak berfungsi. Meskipun -r harus melakukan pekerjaan itu, subdirektori tidak berubah. File gzip hanya dibuat di direktori teratas.
Apa yang kulewatkan di sini?
Btw: Berikut ini adalah bug dalam output verbose, kan? Saat menggunakan opsi -k dan -v
-k, --keep keep (don't delete) input files
-v, --verbose verbose mode
Keluaran verbose mengatakan itu menggantikan file, meskipun "ganti" berarti bahwa file asli tidak ada setelah diganti. Bagaimanapun, ini hanya hal keluaran.
$ ls
index.html subdir1 testfile testfile.css.gz
javaclass.java subdir2 testfile.css
$ gzip -fkv *.css
testfile.css: 6.6% -- replaced with testfile.css.gz
$ ls
index.html subdir1 testfile testfile.css.gz
javaclass.java subdir2 testfile.css
-r
berfungsi 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)Jawaban:
Anda dapat melakukannya dengan for loop untuk menemukan setiap file lalu kompres:
sumber
-r
opsinya tidak berfungsi,-k
dan-f
berfungsi, jadi saya bisa menggunakannya seperti ini: for i infind | grep -E "\.css$|\.html$"
; do gzip -vkf "$ i"; selesai``...`
memberikan string, bukan daftar.for
menggunakan pemisah bidang internal ($IFS
) untuk memutuskan di mana string harus dipecah. Secara default, itu terbagi pada baris, biji, dan spasi, jadi jika Anda memiliki file yang dipanggilnew style.css
, perintahgzip new
dangzip style.css
akan dieksekusi.export IFS=$'\n'
sesaat sebelumfor
loop.Saya akan menggunakan
Ubah
name
keiname
jika Anda ingin mencocokkan ekstensi case-insensitive (yaitu, sertakan.CSS
dan / atau.HTML
ekstensi). Anda dapat menghilangkan/path/to/dir
jika Anda ingin memulai pencarian rekursif dari direktori saat ini.sumber
--keep
switch, ya, itu menyebabkan file asli tetap dipertahankan. Hapus itu jika Anda ingin mereka dihapus setelah di-zip.Untuk mendapatkan daftar file:
Dan untuk gzip semua file itu:
sumber
tar
yang daftar file sebagai output denganfind
, daripada file sendiri?-T
opsitar
memproses input sebagai nama file.Saya menggunakan jawaban steeldriver , tetapi saya ingin melengkapinya dengan opsi
--best
dan--force
.cd
ke dalam folder apa pun dan ketik kode ini. Semua file yang cocok Anda akan di-gzip.--best
untuk rasio kompresi terbaik.--force
untuk menimpa tanpa bertanya apakah sudah ada file yang di-gzip.sumber
Anda bisa menggunakan globstar.
Dengan
globstar
opsi shell diaktifkan, yang Anda butuhkan adalahgzip -vk **/*.{css,html}
.Bash shell memiliki
globstar
opsi yang memungkinkan Anda menulis rekursif gumpalan dengan**
.shopt -s globstar
memungkinkannya. Tapi Anda mungkin tidak ingin melakukan itu untuk perintah lain yang Anda jalankan nanti, jadi Anda bisa menjalankannya dangzip
perintah Anda dalam subkulit sebagai gantinya.Perintah ini
gzip
s semua.css
dan.html
file dalam direktori saat ini salah satu subdirektorinya, salah mereka subdirektori, dll, menjaga file asli (-k
) dan memberitahu Anda apa yang dilakukannya (-v
):Jika Anda ingin mencocokkan nama file dengan case-insensitive sehingga ekstensi dengan beberapa atau semua huruf besar disertakan, maka Anda juga dapat mengaktifkan
nocaseglob
opsi shell:;
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 mengaktifkanglobstar
maka Anda dapat menjalankanshopt -s globstar
; maka Anda bisa menjalankan perintah:Anda dapat menonaktifkan
globstar
denganshopt -u globstar
. Anda dapat memeriksa apakah saat ini diaktifkan denganshopt globstar
.Bagaimana itu bekerja
Kunci untuk bagaimana
gzip
perintah 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 argumengzip
.**/*.{css,html}
menjadi**/*.css **/*.html
.**
, karenaglobstar
) yang nama filenya terdiri dari apa saja (*
) diikuti oleh akhiran yang ditentukan (.css
atau.html
dalam 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: aktifkandotglob
opsi shell.Atau jika Anda ingin pencocokan huruf besar-kecil dan pencocokan nama file yang dimulai dengan
.
: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
find
dengan-exec
, seperti yang dijelaskan steeldriver (dengan{} \;
) atau seperti yang saya jelaskan di bawah (dengan{} +
).Anda dapat menggunakannya
find
dengan-exec
aksi dan+
untuk efisiensi.The
gzip
mendukung perintah yang diberikan nama-nama beberapa file yang akan dikompresi. Tetapifind
perintah ini , meskipun bekerja dengan baik dan tidak akan lambat kecuali jika Anda memiliki banyak file, jalankangzip
perintah sekali untuk setiap file: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
find
beberapa nama file lewatgzip
dan menjalankannya hanya sebanyak yang diperlukan - yang hampir selalu hanya sekali. Untuk melakukannya, gunakan+
sebagai ganti\;
. The+
Argumen harus datang hanya setelah{}
.find
ganti+
dengan nama file tambahan, jika ada.Tidak masalah untuk menggunakan
+
bahkan jika hanya ada beberapa file yang cocok, dan ketika ada banyak dari mereka, itu bisa terasa lebih cepat daripada memilikigzip
doa terpisah untuk setiap file.Seperti disebutkan steeldriver , Anda dapat menggunakan
-iname
alih-alih-name
mencocokkan file yang namanya suka.css
atau.html
tetapi dengan huruf besar berbeda. Ini sesuai dengan mengaktifkannocaseglob
dalamglobstar
metode berbasis yang dijelaskan di atas.Terakhir, Anda mungkin tidak memiliki file atau direktori yang cocok dengan yang dimulai
.
. Tetapi jika Anda melakukannya,find
secara otomatis memasukkan mereka. Jika Anda ingin mengecualikan mereka (seperti yang terjadi padaglobstar
metode -based yang dijelaskan di atas ketikadotglob
dimatikan), Anda dapat :Cara
globstar
berbasis-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
find
ke perintah lain yang memprosesnya jika Anda menggunakan-print0
atau 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). Sebuahfind
perintah dengan-print
tindakan - termasuk perintah find dengan tidak ada tindakan eksplisit, sejak itu-print
adalah default - tidak menghasilkan output yang aman dapat disalurkan atau diberikan kepada perintah lain yang melakukan tindakan pada file.Output yang
find
dihasilkan dengan-print0
action dapat dengan aman disalurkan kexargs -0
(-0
flag memberitahuxargs
untuk mengharapkan input yang dipisahkan nol).sumber
Untuk zip semua file dalam folder / subfolder secara rekursif:
Untuk unzip:
sumber
`
`
sintaks, tetapi masalahnya sepenuhnya berlaku ketika menggunakan$(
)
sintaks juga.)