Sie können Globstar verwenden.
Wenn die globstar
Shell-Option aktiviert ist, benötigen Sie lediglich gzip -vk **/*.{css,html}
.
Die Bash - Shell hat eine globstar
Option , die Sie schreiben rekursive lässt Klackse mit **
. shopt -s globstar
aktiviert es. Möglicherweise möchten Sie dies jedoch nicht für andere Befehle tun, die Sie später ausführen, sodass Sie es und Ihren gzip
Befehl stattdessen in einer Subshell ausführen können .
Dieser Befehl enthält gzip
alle .css
und .html
Dateien im aktuellen Verzeichnis in einem seiner Unterverzeichnisse, in einem ihrer Unterverzeichnisse usw., wobei die Originaldateien ( -k
) beibehalten und Ihnen mitgeteilt werden, was sie tun ( -v
):
(shopt -s globstar; gzip -vk **/*.{css,html})
Wenn Sie Dateinamen ohne Berücksichtigung der Groß- und Kleinschreibung abgleichen möchten, damit diese Erweiterungen mit einigen oder allen Großbuchstaben enthalten sind, können Sie auch die nocaseglob
Shell-Option aktivieren :
(shopt -s globstar nocaseglob; gzip -vk **/*.{css,html})
;
trennt die beiden Befehle und die äußere (
)
bewirkt, dass sie in einer Subshell ausgeführt werden. Das Festlegen einer Shell-Option in einer Subshell führt nicht dazu, dass sie in der aufrufenden Shell festgelegt wird. Wenn Sie es wollen , aktivieren , globstar
dann können Sie laufen shopt -s globstar
; dann können Sie einfach den Befehl ausführen:
gzip -vk **/*.{css,html}
Sie können deaktivieren globstar
mit shopt -u globstar
. Sie können überprüfen, ob es derzeit mit aktiviert ist shopt globstar
.
Wie es funktioniert
Der Schlüssel zur Funktionsweise dieses gzip
Befehls besteht darin, dass die Shell Erweiterungen ausführt, um eine Liste aller Dateien in der Verzeichnishierarchie mit einem übereinstimmenden Namen zu erstellen und dann jeden dieser Dateinamen als Argumente an zu übergeben gzip
.
- Die Klammererweiterung wird
**/*.{css,html}
zu **/*.css **/*.html
.
- Dann erweitert globbing diese beiden Muster in die Namen von Dateien, auf die unter dem aktuellen Verzeichnis zugegriffen werden kann (
**
aufgrund von globstar
), deren Dateinamen aus irgendetwas ( *
) bestehen, gefolgt vom angegebenen Suffix ( .css
oder .html
in diesem Fall).
Dies stimmt nicht mit Dateien überein, deren Namen mit beginnen.
oder die sich in Verzeichnissen befinden, die auf diese Weise benannt wurden. Sie haben wahrscheinlich keine solchen HTML- und CSS-Dateien, und wenn Sie dies tun, möchten Sie sie wahrscheinlich nicht einschließen. Wenn Sie sie jedoch einschließen möchten, können Sie sie je nach Ihren Anforderungen explizit abgleichen. Zum Beispiel, Ändern **/*.{css,html}
zu **/{,.}*.{css,html}
gehören Dateien , die mit beginnen , .
während noch nicht in Ordnern zu suchen , die zu tun.
Wenn Sie möchten, dass sowohl Dateien, deren Namen beginnen, .
als auch Dateien in Verzeichnissen, deren Namen beginnen .
, eingeschlossen werden, gibt es eine sauberere und einfachere Möglichkeit: Aktivieren Sie die dotglob
Shell-Option.
(shopt -s globstar dotglob; gzip -vk **/*.{css,html})
Oder wenn Sie zwischen Groß- und Kleinschreibung unterscheiden und Dateinamen abgleichen möchten , die beginnen mit .
:
(shopt -s globstar nocaseglob dotglob; gzip -vk **/*.{css,html})
Es ist möglich, wenn auch sehr selten, **
sich auf etwas zu Langes auszudehnen.
Wenn Sie eine große Anzahl von Dateien haben, die auf diese Weise benannt wurden, schlägt dies möglicherweise mit einer Fehlermeldung fehl, die erklärt, dass die Shell die Befehlszeile nicht erstellen kann, weil sie zu lang wäre. (Selbst bei Tausenden von Dateien ist dies normalerweise kein Problem.)
gzip
wird überhaupt nicht angerufen, so dass Sie keine halbfertige Arbeit bekommen.
Wenn dieser Fehler auftritt oder wenn Sie sich darüber Sorgen machen, können Sie find
mit verwenden -exec
, entweder wie steeldriver beschreibt (mit {} \;
) oder wie ich unten beschreibe (mit {} +
).
Sie können find
mit der -exec
Aktion und +
für die Effizienz verwenden.
Der gzip
Befehl unterstützt die Angabe von Namen mehrerer zu komprimierender Dateien. Dieser find
Befehl funktioniert zwar gut und ist nur dann langsam, wenn Sie über viele Dateien verfügen . Er führt den gzip
Befehl jedoch einmal für jede Datei aus:
find . \( -name \*.css -o -name \*.html \) -exec gzip -vk {} \;
Dies funktioniert und Sie können es definitiv verwenden. ( .
Sucht aus dem aktuellen Verzeichnis. Außerdem ist es eine etwas andere Art, den Befehl in die sehr gute Antwort von steeldriver zu schreiben . Sie können den von Ihnen bevorzugten Stil verwenden.)
Sie können auch find
mehrere Dateinamen übergeben gzip
und nur so oft wie nötig ausführen - was fast immer nur einmal der Fall ist. Um dies zu erreichen , verwenden +
statt\;
. Das +
Argument sollte gleich danach kommen {}
. find
wird +
durch zusätzliche Dateinamen ersetzt, falls vorhanden.
find . \( -name \*.css -o -name \*.html \) -exec gzip -vk {} +
Die Verwendung ist in Ordnung, +
auch wenn nur wenige übereinstimmende Dateien vorhanden sind. Wenn viele vorhanden sind, kann dies spürbar schneller sein als ein separater gzip
Aufruf für jede Datei.
Wie steeldriver erwähnt , können Sie -iname
anstelle von -name
Dateien abgleichen , deren Name wie .css
oder .html
aber mit unterschiedlicher Groß- und Kleinschreibung endet . Dies entspricht dem Aktivieren nocaseglob
in dem globstar
oben beschriebenen basierenden Verfahren.
Schließlich haben Sie wahrscheinlich keine passenden Dateien oder Verzeichnisse, die mit beginnen .
. Wenn Sie dies jedoch tun, werden sie find
automatisch eingeschlossen. Wenn Sie sie ausschließen möchten (wie dies bei der globstar
oben beschriebenen Methode der Fall ist, wenn sie deaktiviert dotglob
ist), können Sie :
find . -not -path '*/.*' \( -name \*.css -o -name \*.html \) -exec gzip -vk {} +
Die globstar
oben beschriebene Methode ist einfacher zu schreiben, insbesondere wenn Sie Verzeichnisse und Dateien ausschließen, die mit beginnen .
, da dies die Standardeinstellung ist.
Was nicht zu tun ...
Dateinamen können beliebige Zeichen außer dem Pfadtrennzeichen /
und dem Nullzeichen enthalten . Es gibt viele Techniken, die bei seltsamen Dateinamen brechen, und sie sind normalerweise komplizierter als Techniken, die immer nur funktionieren. Ich schlage daher vor, sie zu vermeiden, selbst wenn Sie wissen (oder glauben, dass Sie es wissen), dass sie in Ihrer spezifischen Situation in Ordnung sind. Und natürlich Sie müssen sie nicht verwenden , wenn Sie Dateinamen mit Zeichen haben könnten , die speziell behandelt werden können, einschließlich Leerzeichen.
Es ist möglich, die Ausgabe sicher find
an einen anderen Befehl weiterzuleiten , der sie verarbeitet, wenn Sie -print0
eine ähnliche Aktion verwenden, um ein Nullzeichen zwischen Pfaden anstelle einer neuen Zeile zu platzieren , und nicht anders. Dateinamen können Zeilenumbrüche enthalten (obwohl ich Sie davon abhalte, absichtlich Dateien mit ihnen zu benennen). Ein find
Befehl mit der -print
Aktion - einschließlich Suchbefehlen ohne explizite Aktion, da dies -print
die Standardeinstellung ist - erzeugt keine Ausgabe, die sicher an einen anderen Befehl weitergeleitet oder anderweitig bereitgestellt werden kann, der eine Aktion für die Dateien ausführt.
Die find
mit der -print0
Aktion erzeugte Ausgabe kann sicher an weitergeleitet werden xargs -0
(das -0
Flag weist darauf hin xargs
, dass eine durch Null getrennte Eingabe zu erwarten ist).
-r
funktioniert wie geplant. Von man gzip : Durchlaufen Sie die Verzeichnisstruktur rekursiv. Wenn einer der in der Befehlszeile angegebenen Dateinamen Verzeichnisse sind , steigt gzip in das Verzeichnis ab und komprimiert alle dort gefundenen Dateien (oder dekomprimiert sie im Fall von gunzip). (Hervorhebung von mir)