Ich versuche, alle Dateien auf Ubuntu mit der Dateierweiterung .css, .html oder .js zu komprimieren. in einem Top-Verzeichnis und allen Unterverzeichnissen. Ich möchte die Originaldateien behalten und die GZ-Datei überschreiben, falls bereits vorhanden.
Wenn ich also n Dateien habe, möchte ich diese n Dateien behalten und zusätzliche n Archivdateien erstellen. Nicht nur einer.
Mein Versuch war, ein Skript auszuführen, das so aussieht:
gzip -rkf *.css
gzip -rkf *.html
... one line for each file extension
Erstens: Ich muss eine Zeile in diesem Skript für jede Dateierweiterung haben, die ich gzipen möchte. Das ist in Ordnung, aber ich hoffe, einen besseren Weg zu finden
Zweitens und wichtiger: Es funktioniert nicht. Obwohl -r die Aufgabe übernehmen sollte, bleiben die Unterverzeichnisse unverändert. Die gzip-Datei wird nur im obersten Verzeichnis erstellt.
Was fehlt mir hier?
Übrigens: Das Folgende ist ein Fehler in der ausführlichen Ausgabe, richtig? Bei Verwendung der Optionen -k und -v
-k, --keep keep (don't delete) input files
-v, --verbose verbose mode
Die ausführliche Ausgabe besagt, dass die Datei ersetzt wird, obwohl "Ersetzen" bedeutet, dass die Originaldatei nach dem Ersetzen nicht vorhanden ist. Auf jeden Fall ist dies nur die Ausgabesache.
$ 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
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)Antworten:
Sie können dies mit einer for-Schleife tun, um jede Datei zu finden und dann zu komprimieren:
quelle
-r
Option nicht funktioniert-k
und-f
funktioniert, kann ich sie folgendermaßen verwenden: for i infind | grep -E "\.css$|\.html$"
; mache gzip -vkf "$ i"; erledigt``...`
eine Zeichenfolge bereit, keine Liste.for
verwendet das interne Feldtrennzeichen ($IFS
), um zu entscheiden, wo diese Zeichenfolge aufgeteilt werden soll. Standardmäßig werden Zeilenvorschübe, Tabulatoren und Leerzeichen aufgeteilt. Wenn Sie also eine Datei mit dem Namen habennew style.css
, werden die Befehlegzip new
undgzip style.css
ausgeführt.export IFS=$'\n'
kurz vor derfor
Schleife ausführen .ich würde ... benutzen
Wechseln Sie
name
zu,iname
wenn Sie die Erweiterungen ohne Berücksichtigung der Groß- und Kleinschreibung abgleichen möchten (dh Include.CSS
und / oder.HTML
Erweiterungen). Sie können das weglassen,/path/to/dir
wenn Sie die rekursive Suche aus dem aktuellen Verzeichnis starten möchten.quelle
--keep
Wechsel wundern , werden die Originaldateien beibehalten. Lassen Sie es weg, wenn Sie möchten, dass sie nach dem Komprimieren gelöscht werden.So erhalten Sie die Liste der Dateien:
Und um all diese Dateien zu gzipen:
quelle
tar
die Liste der Dateien, die von ausgegeben werdenfind
, und nicht die Dateien selbst?-T
Optiontar
verarbeitet die Eingabe als Dateinamen.Ich habe die Antwort von steeldriver verwendet , aber ich möchte sie mit den Optionen
--best
und vervollständigen--force
.cd
in einen beliebigen Ordner und geben Sie diesen Code ein. Alle Ihre passenden Dateien werden komprimiert.--best
für das beste Kompressionsverhältnis.--force
zum Überschreiben , ohne zu fragen , ob es bereits eine gzip - Datei ist.quelle
Sie können Globstar verwenden.
Wenn die
globstar
Shell-Option aktiviert ist, benötigen Sie lediglichgzip -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 Ihrengzip
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
):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 :;
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 laufenshopt -s globstar
; dann können Sie einfach den Befehl ausführen:Sie können deaktivieren
globstar
mitshopt -u globstar
. Sie können überprüfen, ob es derzeit mit aktiviert istshopt 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 übergebengzip
.**/*.{css,html}
zu**/*.css **/*.html
.**
aufgrund vonglobstar
), 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 diedotglob
Shell-Option.Oder wenn Sie zwischen Groß- und Kleinschreibung unterscheiden und Dateinamen abgleichen möchten , die beginnen mit
.
: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. Dieserfind
Befehl funktioniert zwar gut und ist nur dann langsam, wenn Sie über viele Dateien verfügen . Er führt dengzip
Befehl jedoch einmal für jede Datei aus: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 übergebengzip
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.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 separatergzip
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 Aktivierennocaseglob
in demglobstar
oben beschriebenen basierenden Verfahren.Schließlich haben Sie wahrscheinlich keine passenden Dateien oder Verzeichnisse, die mit beginnen
.
. Wenn Sie dies jedoch tun, werden siefind
automatisch eingeschlossen. Wenn Sie sie ausschließen möchten (wie dies bei derglobstar
oben beschriebenen Methode der Fall ist, wenn sie deaktiviertdotglob
ist), können Sie :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). Einfind
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 werdenxargs -0
(das-0
Flag weist darauf hinxargs
, dass eine durch Null getrennte Eingabe zu erwarten ist).quelle
So rekursieren Sie alle Dateien in einem Ordner / Unterordner rekursiv:
Entpacken:
quelle
`
`
Syntax geschrieben, aber das Problem tritt auch bei Verwendung der$(
)
Syntax vollständig auf .)