Możesz użyć globstar.
Po włączeniu globstar
opcji powłoki wszystko czego potrzebujesz to gzip -vk **/*.{css,html}
.
Powłoka Bash ma globstar
opcję, która pozwala pisać rekurencyjnych globs z **
. shopt -s globstar
umożliwia to. Ale możesz nie chcieć tego robić w przypadku innych poleceń uruchamianych później, aby zamiast tego można było uruchomić je i gzip
polecenie w podpowłoce .
To polecenie gzip
s wszystkich .css
i .html
plików w bieżącym katalogu dowolnego z jego podkatalogów, dowolnego z ich podkatalogów itp., Zachowując oryginalne pliki ( -k
) i informując o tym, co robi ( -v
):
(shopt -s globstar; gzip -vk **/*.{css,html})
Jeśli chcesz dopasować nazwy plików bez rozróżniania wielkości liter, aby te rozszerzenia z niektórymi lub wszystkimi literami były włączone, możesz również włączyć nocaseglob
opcję powłoki:
(shopt -s globstar nocaseglob; gzip -vk **/*.{css,html})
;
rozdziela dwa polecenia, a zewnętrzny (
)
powoduje, że są one uruchamiane w podpowłoce. Ustawienie opcji powłoki w podpowłoce nie powoduje ustawienia jej w powłoce wywołującej. Jeśli nie chcesz, aby umożliwić globstar
następnie można uruchomić shopt -s globstar
; możesz po prostu uruchomić polecenie:
gzip -vk **/*.{css,html}
Możesz wyłączyć za globstar
pomocą shopt -u globstar
. Możesz sprawdzić, czy jest on obecnie włączony za pomocą shopt globstar
.
Jak to działa
Kluczem do działania tego gzip
polecenia jest to, że powłoka wykonuje na nim rozszerzenia, aby utworzyć listę każdego pliku w hierarchii katalogów o pasującej nazwie, a następnie przekazuje każdą z tych nazw plików jako argumenty gzip
.
- Ekspansja nawiasów zamienia się
**/*.{css,html}
w **/*.css **/*.html
.
- Następnie globbing rozszerza te dwa wzorce na nazwy plików dostępnych w bieżącym katalogu (z
**
powodu globstar
), których nazwy plików składają się ze wszystkiego ( *
), po którym następuje określony sufiks ( .css
lub .html
w tym przypadku).
To nie pasuje do plików, których nazwy zaczynają się od,.
ani tych, które znajdują się w katalogach o takich nazwach. Prawdopodobnie nie masz takich plików HTML i CSS, a jeśli tak, prawdopodobnie nie chcesz ich dołączać. Ale jeśli chcesz je dołączyć, możesz je jednoznacznie dopasować w zależności od potrzeb. Na przykład zmiana **/*.{css,html}
na **/{,.}*.{css,html}
obejmuje pliki, które zaczynają się od, .
ale nadal nie wyszukują w folderach, które to robią.
Jeśli chcesz uwzględnić zarówno pliki, których nazwy zaczynają się od, jak .
i pliki w katalogach, których nazwy zaczynają się .
od, to jest prostszy i prostszy sposób: włącz dotglob
opcję powłoki.
(shopt -s globstar dotglob; gzip -vk **/*.{css,html})
Lub jeśli chcesz rozróżniać małe i wielkie litery oraz nazwy plików rozpoczynające się od .
:
(shopt -s globstar nocaseglob dotglob; gzip -vk **/*.{css,html})
Możliwe jest, choć bardzo rzadkie, **
rozwinięcie się w coś zbyt długiego.
Jeśli masz ogromną liczbę plików nazwanych w ten sposób, to może zakończyć się niepowodzeniem z komunikatem o błędzie, wyjaśniając, że powłoka nie można zbudować z wiersza poleceń, ponieważ byłoby to zbyt długo. (Nawet w przypadku tysięcy plików zwykle nie stanowi to problemu).
gzip
nie zostanie w ogóle wezwany, więc nie dostaniesz w połowie wykonanej pracy.
Jeśli wystąpi ten błąd lub martwisz się nim, możesz użyć find
go -exec
, tak jak opisuje steeldriver (z {} \;
) lub jak opisuję poniżej (z {} +
).
Możesz używać find
z -exec
akcją i +
dla wydajności.
Te gzip
podpory polecenia są podane nazwy wielu plików mają być kompresowane. Ale to find
polecenie, chociaż działa dobrze i nie będzie wolne, chyba że masz wiele plików, uruchamia gzip
polecenie raz dla każdego pliku:
find . \( -name \*.css -o -name \*.html \) -exec gzip -vk {} \;
To działa i na pewno możesz go użyć. ( .
wyszukuje z bieżącego katalogu. Poza tym jest to naprawdę nieco inny sposób pisania polecenia w bardzo dobrej odpowiedzi steeldriver ; możesz użyć dowolnego stylu).
Możesz także find
przekazać wiele nazw plików gzip
i uruchomić go tyle razy, ile to konieczne - co prawie zawsze jest tylko raz. Aby to zrobić, użyj +
zamiast\;
. +
Argument powinien przyjść tuż po {}
. find
zastępuje +
dodatkowymi nazwami plików, jeśli istnieją.
find . \( -name \*.css -o -name \*.html \) -exec gzip -vk {} +
Można z niego korzystać, +
nawet jeśli jest tylko kilka pasujących plików, a gdy jest ich wiele, może być zauważalnie szybsze niż oddzielne gzip
wywołanie dla każdego pliku.
Jak steeldriver wspomina , można użyć -iname
zamiast -name
dopasować pliki, których nazwa koniec jak .css
albo .html
ale o różnej kapitalizacji. Odpowiada to włączeniu nocaseglob
w globstar
metodzie opisanej powyżej.
Wreszcie prawdopodobnie nie masz żadnych pasujących plików lub katalogów, które zaczynają się od .
. Ale jeśli to zrobisz, find
automatycznie je uwzględni. Jeśli chcesz je wykluczyć (jak to się dzieje w przypadku globstar
metody opartej na szczegółach powyżej, gdy dotglob
jest wyłączona), możesz :
find . -not -path '*/.*' \( -name \*.css -o -name \*.html \) -exec gzip -vk {} +
globstar
-Na sposób opisany powyżej jest prostsze pisać, zwłaszcza jeśli jesteś z wyłączeniem katalogów i plików, które zaczynają się .
, ponieważ jest to ustawienie domyślne.
Czego nie robić ...
Nazwy plików mogą zawierać dowolny znak oprócz separatora ścieżki /
i znaku zerowego . Istnieje wiele technik, które łamią się na dziwnych nazwach plików i są zwykle bardziej skomplikowane niż techniki, które zawsze działają. Sugeruję więc unikanie ich, nawet jeśli wiesz (lub wydaje ci się, że wiesz), że są w porządku w twojej konkretnej sytuacji. I oczywiście, że należy nie używać ich, czy może masz nazwy plików ze znakami, które mogą być traktowane specjalnie, łącznie ze spacjami.
Możliwe jest bezpieczne przesyłanie danych wyjściowych find
do innego polecenia, które je przetwarza, jeśli użyjesz -print0
lub podobnej akcji, aby spowodować umieszczenie znaku pustego między ścieżkami zamiast nowej linii , a nie inaczej. Nazwy plików mogą zawierać znaki nowej linii (choć zniechęcam cię do celowego nazywania ich plikami). find
Komenda z -print
akcji - w tym polecenia find bez wyraźnego działania, ponieważ wtedy -print
jest domyślna - nie powoduje wyjście, które można bezpiecznie doprowadzanej rurami lub inaczej dostarczane do innego polecenia, które wykonuje czynność na plikach.
Dane wyjściowe find
tworzone za pomocą -print0
akcji mogą być bezpiecznie przesyłane do potoku xargs -0
( -0
flaga informuje, xargs
że należy oczekiwać danych wejściowych oddzielonych od wartości zerowej).
-r
działa zgodnie z przeznaczeniem. Z man gzip : Rekurencyjnie przeglądaj strukturę katalogów. Jeśli którakolwiek z nazw plików określonych w wierszu poleceń to katalogi , gzip zejdzie do katalogu i skompresuje wszystkie znalezione tam pliki (lub rozpakuje je w przypadku gunzip). (moje podkreślenie)