belirli uzantılara sahip tüm dosyaları gzip


11

Ben ubuntu dosya uzantısı .css, .html veya .js olan tüm dosyaları gzip çalışıyorum. bir üst dizinde ve tüm alt dizinlerde. Orijinal dosyaları saklamak ve zaten varsa .gz dosyasının üzerine yazmak istiyorum.

Bu yüzden n dosyam olduğunda, bu n dosyaları saklamak ve ek n arşiv dosyaları oluşturmak istiyorum. Sadece bir tane deđil.

Benim denemem şöyle bir komut dosyası çalıştırmak oldu:

gzip -rkf *.css
gzip -rkf *.html
... one line for each file extension

İlk: gzip istiyorum her dosya uzantısı için bu komut dosyasında bir satır olması gerekir. Sorun değil, ama daha iyi bir yol bulmayı umuyorum

İkincisi ve daha önemlisi: Çalışmıyor. -R işi yapsa da, alt dizinler değişmez. Gzip dosyası yalnızca üst dizinde oluşturulur.

Burada ne eksik?

Btw: Aşağıdaki ayrıntılı çıktıda bir hata, değil mi? -K ve -v seçeneğini kullanırken

-k, --keep        keep (don't delete) input files
-v, --verbose     verbose mode

Ayrıntılı çıktı dosyayı değiştirdiğini söylese de, "replace", orijinal dosyanın değiştirmeden sonra mevcut olmadığı anlamına gelir. Her neyse, bu sadece çıktı şey.

$ 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

1
-rtasarlandığı gibi çalışır. Man gzip Gönderen : Dizin yapısını tekrar tekrar seyahat. Komut satırında belirtilen dosya adlarından herhangi biri dizinse, gzip dizine iner ve orada bulduğu tüm dosyaları sıkıştırır (veya gunzip durumunda bunları açar). (Vurgu madeni)
Dennis

Tamam. Yani -r, XYZ.css adında bir dizin girecektir. Sonra özyineleme beklediğim gibi tasarlanmamıştır.
Sadik

Yanıtlar:


7

bunu bir for döngüsü ile her dosyayı bulmak ve sonra sıkıştırmak için yapabilirsiniz:

for i in `find | grep -E "\.css$|\.html$"`; do gzip "$i" ; done

Teşekkür ederim! Gerçi -rseçenek değil işi yapar -kve -fbu gibi kullanabilirsiniz, böylece çalışıyoruz: i için find | grep -E "\.css$|\.html$"; gzip -vkf "$ i" yapın; done`
Sadik

@Sadik: Dikkat et! Dosya adlarından herhangi birinde boşluk varsa bu yaklaşım işe yaramaz.
Dennis

Neden olmasın açıklayabilir misin?
Sadik

1
@Sadik: `...`bir liste değil, bir dize sağlar. bu dizenin nereye bölünmesi gerektiğine karar vermek foriçin dahili alan ayırıcısını ( $IFS) kullanır . Varsayılan olarak, satır beslemelerine, sekmelere ve boşluklara ayrılır, bu nedenle adlı bir dosyanız varsa new style.css, komutlar gzip newve gzip style.cssyürütülür.
Dennis

1
@Sadik, Dennis haklı, döngüden export IFS=$'\n'hemen önce çalıştırabileceğiniz hızlı bir çözüm for.
mndo

14

Kullanmak istiyorum

find /path/to/dir \( -name '*.css' -o -name '*.html' \) -exec gzip --verbose --keep {} \;

Değişim nameiçin inamesize küçük harf duyarsız uzantıları eşleştirmek istiyorsanız (yani dahil .CSSve / veya .HTMLuzantıları). /path/to/dirGeçerli dizinden özyinelemeli aramayı başlatmak istiyorsanız , atlayabilirsiniz .


2
--keepGeçiş hakkında merak edenler için , evet, orijinal dosyaların korunmasına neden olur. Bir kez sıkıştırıldıktan sonra silinmelerini istiyorsanız bunu atlayın.
Ben Johnson

4

Dosyaların listesini almak için:

find -type f | grep -P '\.js|\.html|\.css'

Ve tüm bu dosyaları sıkıştırmak için:

find -type f | grep -P '\.js|\.html|\.css' | tar cvzf archive.gz -T -

Değil bu misiniz listesi çıktı olarak dosyaları tarafından değil, dosyalar kendilerini daha? tarfind
Jos

Her css, html veya js dosyası için bir arşiv dosyasına sahip olmak istediğimi açıklığa kavuşturmak için sorumu düzenledim.
Sadik

2
@ -TSeçenek ile birlikte no tar, girdiyi dosya adları olarak işler.
chaos

@chaos Ah, teşekkür ederim. Bugün bir şey öğrendim.
Jos

2

Steeldriver'ın cevabını kullandım , ancak --bestve --forceseçenekleriyle tamamlamayı seviyorum .

cdherhangi bir klasöre girin ve bu kodu yazın. Eşleşen tüm dosyalarınız sıkıştırılacaktır.

find . \( -name '*.css' -o -name '*.js' \) -exec gzip --verbose --keep --best --force {} \;
  • --bestEn iyi sıkıştırma oranı için kullanın .
  • --forceZaten sıkıştırılmış bir dosya olup olmadığını sormadan üzerine yazmak için kullanın .

1

Globstar kullanabilirsiniz.

İle globstarkabuk seçeneği etkin, tüm ihtiyaç vardır gzip -vk **/*.{css,html}.

Bash kabuğu, globstartekrarlayan globları yazmanıza izin veren bir seçeneğe sahiptir **. shopt -s globstarsağlar. Ancak daha sonra çalıştırdığınız diğer komutlar için bunu yapmak istemeyebilirsiniz, böylece onu ve gzip komutunuzu bir alt kabukta çalıştırabilirsiniz .

Bu komut gziphepsi .cssve .htmlherhangi onun alt dizinleri geçerli dizindeki dosyaları, herhangi onların vb alt dizinleri, (orijinal dosyaları tutmak -k) ve (ne yaptığını söylüyorum -v):

(shopt -s globstar; gzip -vk **/*.{css,html})

Dosya adlarını büyük / küçük harfe duyarlı olmayan şekilde eşleştirmek istiyorsanız, büyük veya küçük harfli uzantıların dahil edilmesi için nocaseglobkabuk seçeneğini de etkinleştirebilirsiniz :

(shopt -s globstar nocaseglob; gzip -vk **/*.{css,html})

;iki komutu ayırır ve dış ( )kısım bir alt kabukta çalıştırılmalarına neden olur. Alt kabukta bir kabuk seçeneği ayarlamak, çağrının kabukta ayarlanmasına neden olmaz. Eğer varsa do etkinleştirmek istediğiniz globstarardından çalıştırabilirsiniz shopt -s globstar; o zaman sadece komutu çalıştırabilirsiniz:

gzip -vk **/*.{css,html}

Sen devre dışı bırakabilirsiniz globstarile shopt -u globstar. Şu anda ile etkin olup olmadığını kontrol edebilirsiniz shopt globstar.

Nasıl çalışır

Bu gzipkomutun nasıl çalıştığının anahtarı , kabuğun dizin hiyerarşisinde eşleşen bir ada sahip her dosyanın bir listesini üretmek için genişletmeler gerçekleştirmesi ve ardından bu dosya adlarının her birini bağımsız değişken olarak geçirmesidir gzip.

  • Ayraç genişleme döner **/*.{css,html}içine **/*.css **/*.html.
  • Daha sonra globbing , bu iki kalıbı, dosya adları belirtilen son ekin ( veya bu durumda) izlediği herhangi bir şeyden ( ) oluşan geçerli dizinin altında erişilebilen ( **nedeniyle globstar) dosya adlarına genişletir .*.css.html

Bu, adları ile başlayan. veya bu şekilde adlandırılan dizinlerde bulunan dosyalarla eşleşmez . Muhtemelen böyle bir HTML ve CSS dosyanız yok ve eğer eklerseniz, muhtemelen bunları dahil etmek istemezsiniz. Ancak bunları dahil etmek istiyorsanız, ihtiyaçlarınıza bağlı olarak bunları açıkça eşleştirebilirsiniz. Örneğin, değişen **/*.{css,html}etmek **/{,.}*.{css,html}ile başlayan dosyaları içerir .hala ederken değil yapmak klasörlerde arama.

Hem adları ile başlayan dosyaların hem de adları ile başlayan .dizinlerdeki dosyaların .dahil edilmesini istiyorsanız, daha temiz ve basit bir yol vardır: dotglobkabuk seçeneğini etkinleştirin .

(shopt -s globstar dotglob; gzip -vk **/*.{css,html})

Veya aşağıdakilerle başlayan dosya adlarının büyük / küçük harfe duyarsız eşleşmesini ve eşleşmesini istiyorsanız .:

(shopt -s globstar nocaseglob dotglob; gzip -vk **/*.{css,html})

Çok nadir olsa da, **çok uzun bir şeye genişlemek mümkündür .

Bu şekilde adlandırılmış çok sayıda dosyanız varsa , bu durum kabuğun çok uzun olacağı için komut satırını oluşturamayacağını açıklayan bir hata iletisiyle başarısız olabilir. (Binlerce dosyada bile, bu genellikle bir sorun değildir.)

gzip hiç çağrılmaz, bu yüzden yarı iş yaparsınız.

Bu hata olursa bu konuda endişeli iseniz veya kullanabileceğiniz findile -exec, ya olduğu steeldriver açıklanır (ile {} \;) veya I (aşağıda tarif {} +).

Sen kullanabilirsiniz findile -execeylem ve +etkinlik için.

gzipKomut destekleri birden fazla dosya isimleri sıkıştırılacak veriliyor. Ancak bu findkomut, iyi çalışmasına ve çok fazla dosyanız yoksa yavaş olmayacak olmasına rağmen , her dosya gzipiçin komutu bir kez çalıştırır :

find . \( -name \*.css -o -name \*.html \) -exec gzip -vk {} \;

Bu işe yarıyor ve kesinlikle kullanabilirsiniz. ( .geçerli dizinden arama yapar. Bunun yanı sıra, komut satırını steeldriver'ın çok iyi cevabına yazmanın biraz farklı bir yolu ; tercih ettiğiniz stili kullanabilirsiniz.)

Ayrıca, findbirden fazla dosya adı geçebilir gzipve yalnızca gerektiği kadar çok çalıştırabilirsiniz - neredeyse her zaman sadece bir kez. Bunu yapmak için +yerine kullanın\; . +Argüman hemen sonra gelmelidir {}. varsa ek dosya adlarıyla finddeğiştirilir +.

find . \( -name \*.css -o -name \*.html \) -exec gzip -vk {} +

+Yalnızca birkaç eşleşen dosya olsa bile kullanmak iyidir ve bunların birçoğu olduğunda, gzipher dosya için ayrı bir çağırmadan belirgin şekilde daha hızlı olabilir .

Gibi steeldriver bahseder kullanabileceğiniz -inameyerine -namedosyaları ismi ucu gibi eşleşecek .cssya .htmlama farklı büyük harf. Bu nocaseglob,globstar merkezli bir yöntem, yukarıda tarif edilen.

Son olarak, muhtemelen ile başlayan eşleşen dosya veya dizinlere sahip değilsiniz .. Ancak bunu yaparsanız, findbunları otomatik olarak ekler. Bunları hariç tutmak istiyorsanız ( globstaryukarıda dotglobkapalı olduğunda ayrıntılı olarak açıklanan -based yönteminde olduğu gibi) şunları yapabilirsiniz :

find . -not -path '*/.*' \( -name \*.css -o -name \*.html \) -exec gzip -vk {} +

globstarTabanlı yolu yukarıda anlatılan genel olarak başlangıçta hariç dizinleri ve dosyaları özellikle eğer, yazma daha basittir .varsayılan beri.

Ne değil ...

Dosya adları yol ayırıcı /ve boş karakter dışında herhangi bir karakter içerebilir . Tuhaf dosya adlarını bozan birçok teknik vardır ve genellikle her zaman çalışan tekniklerden daha karmaşıktır . Bu nedenle, sizin özel durumunuzda iyi olduklarını bildiğinizde (veya bildiğinizi düşündüğünüzde bile) bunlardan kaçınmanızı öneririm. Ve elbette gerekir Eğer boşluklar dahil özel olarak tedavi edilebilir karakterler ile dosya olabilir eğer bunları kullanmayın.

Aksi takdirde, satırlar arasına satırlar arasına boş bir karakter yerleştirmesine neden olması için kullanırsanız,find onu işleyen başka bir komutun veya benzer bir eylemin çıktısını güvenli bir şekilde bağlamak mümkündür . Dosya adları yeni satırlar içerebilir (ancak dosyaları kasıtlı olarak bunlarla adlandırmaktan vazgeçirmeme rağmen). Eylemi içeren bir komut - o zamandan beri açık bir eylemi olmayan bulma komutları dahil-print0find-print-print , varsayılan olduğundan - dosyalar üzerinde bir eylem gerçekleştiren başka bir komuta güvenli bir şekilde iletilebilen veya başka bir şekilde sağlanabilen çıktı üretmez.

Eylem findile üretilen çıktı -print0güvenli bir şekilde bağlanabilir xargs -0( -0bayrak xargsboş ayırılmış girdi beklemeyi söyler ).


0

Bir klasördeki / alt klasördeki tüm dosyaları özyinelemeli olarak sıkıştırmak için:

gzip -r `find . -type f -name "*.html"` 

Sıkıştırmak için:

gunzip -r `find . -type f -name "*.gz"` 

Bu komut ikame tabanlı yöntem sıklıkla kırılır ve oldukça kötüdür. Sorun boşluk veya diğer boşluk içeren dosya adlarının bölünüp birden çok dosya adı olarak işlem görmesidir. (Bu komutlar ` `sözdizimi kullanılarak yazılır , ancak sözdizimi kullanılırken de sorun tam olarak uygulanır $( ).)
Eliah Kagan
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.