Próbuję zgzipować wszystkie pliki na Ubuntu, które mają rozszerzenie .css, .html lub .js. w głównym katalogu i wszystkich podkatalogach. Chcę zachować oryginalne pliki i zastąpić plik .gz, jeśli już istnieje.
Więc kiedy mam n plików, chcę zachować te n plików i utworzyć dodatkowe n plików archiwum. Nie tylko jeden.
Moja próba polegała na uruchomieniu skryptu, który wygląda następująco:
gzip -rkf *.css
gzip -rkf *.html
... one line for each file extension
Po pierwsze: muszę mieć jedną linię w tym skrypcie dla każdego rozszerzenia pliku, które chcę gzip. W porządku, ale mam nadzieję, że znajdę lepszy sposób
Drugi i ważniejszy: to nie działa. Chociaż -r powinien wykonać zadanie, podkatalogi pozostają niezmienione. Plik gzip jest tworzony tylko w górnym katalogu.
Czego tu brakuje?
Btw: Poniżej znajduje się błąd w pełnych wynikach, prawda? Podczas korzystania z opcji -k i -v
-k, --keep keep (don't delete) input files
-v, --verbose verbose mode
Pełne wyjście mówi, że zastępuje plik, chociaż „zamień” oznacza, że oryginalny plik nie istnieje po zamianie. W każdym razie jest to tylko wynik.
$ 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
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)Odpowiedzi:
możesz to zrobić za pomocą pętli for, aby znaleźć każdy plik, a następnie skompresować go:
źródło
-r
opcja nie działa-k
i-f
działa, więc mogę użyć ich w następujący sposób: dla mnie wfind | grep -E "\.css$|\.html$"
; do gzip -vkf "$ i"; zrobione``...`
zapewnia ciąg, a nie listę.for
używa wewnętrznego separatora pól ($IFS
), aby zdecydować, gdzie ten ciąg powinien zostać podzielony. Domyślnie dzieli się na linie, tabulatory i spacje, więc jeśli masz plik o nazwienew style.css
, poleceniagzip new
igzip style.css
zostaną wykonane.export IFS=$'\n'
tuż przedfor
pętlą.użyłbym
Zmień
name
na,iname
jeśli chcesz dopasować rozszerzenia bez rozróżniania wielkości liter (tj. Dołącz.CSS
i / lub.HTML
rozszerzenia). Możesz pominąć opcję,/path/to/dir
jeśli chcesz rozpocząć wyszukiwanie rekurencyjne z bieżącego katalogu.źródło
--keep
przełącznikiem, tak, powoduje to zachowanie oryginalnych plików. Pomiń, jeśli chcesz, aby zostały usunięte po zgzipowaniu.Aby uzyskać listę plików:
I gzip wszystkie te pliki:
źródło
tar
find
-T
opcjątar
przetwarza dane wejściowe jako nazwy plików.Kiedyś odpowiedź steeldriver jest , ale chciałbym, aby zakończyć go z
--best
i--force
opcji.cd
w dowolnym folderze i wpisz ten kod. Wszystkie pasujące pliki zostaną skompresowane.--best
dla najlepszego współczynnika kompresji.--force
do zastępowania bez pytania, czy istnieje już plik spakowany gzip.źródło
Możesz użyć globstar.
Po włączeniu
globstar
opcji powłoki wszystko czego potrzebujesz togzip -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 igzip
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
):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:;
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: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 argumentygzip
.**/*.{css,html}
w**/*.css **/*.html
.**
powoduglobstar
), 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łączdotglob
opcję powłoki.Lub jeśli chcesz rozróżniać małe i wielkie litery oraz nazwy plików rozpoczynające się od
.
: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 tofind
polecenie, chociaż działa dobrze i nie będzie wolne, chyba że masz wiele plików, uruchamiagzip
polecenie raz dla każdego pliku: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ówgzip
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ą.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ż oddzielnegzip
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łączeniunocaseglob
wglobstar
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 przypadkuglobstar
metody opartej na szczegółach powyżej, gdydotglob
jest wyłączona), możesz :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 potokuxargs -0
(-0
flaga informuje,xargs
że należy oczekiwać danych wejściowych oddzielonych od wartości zerowej).źródło
Aby rekurencyjnie skompresować wszystkie pliki w folderze / podfolderze:
Odsunąć zamek błyskawiczny:
źródło
`
`
składni, ale problem w pełni dotyczy również korzystania ze$(
)
składni.)