Wie erstelle ich eine gzip-Datei ohne .gz-Dateierweiterung?

14

Ich möchte eine gezippte Datei erstellen, die den ursprünglichen Dateinamen beibehält. Zum Beispiel sollte gzipping "example.txt" eine gzippte Datei mit dem Namen "example.txt" anstelle von "example.txt.gz" ausgeben. Ist es möglich, dies elegant mit einem Befehl zu tun (ohne einen nachfolgenden zu tun mv)?

Jamieb
quelle
4
Ich bin ein bisschen neugierig. Warum willst du das? Es klingt nach einer schlechten Idee.
Bernhard
3
Ja. Sie schreiben 2 ganze Zeilen in ein Bash-Skript und nennen es "my-elegant-command". ;)
Goldlöckchen
2
@Bernhard Es ist Teil eines kontinuierlichen Integrationserstellungsprozesses für eine Web-App. Statische Assets (CSS, JS-Dateien) müssen komprimiert werden, ohne den Dateinamen zu ändern. Bei Auslieferung an den Browser ist ein Header "content-encoding: gzip" enthalten, sodass die Erweiterung keine Rolle spielt. Wenn sich der Dateiname ändert, muss ich in den HTML-Quelldateien suchen und ersetzen.
Jamieb
Wenn dies wirklich ein Problem für Sie ist, können Sie eine Bash-Funktion definieren, die $ * an die ausführbare gzip-Datei übergibt, und die zweite Zeile erledigt die mv für Sie.
Bratchley
4
@Ihr Web-App-Problem: Jeder anständige Webserver kann / wird die Komprimierung für Sie tun ...
Bananguin

Antworten:

12

Das funktioniert nicht:

# echo Hello World > example.txt
# gzip < example.txt > example.txt # WRONG!
# file example.txt
example.txt: gzip compressed data, from Unix, last modified: Thu Mar 21 19:45:29 2013
# gunzip < example.txt
<empty file>

Dies ist eine Rennbedingung:

# echo Hello World > example.txt
# dd if=example.txt | gzip | dd of=example.txt # still WRONG!
# gunzip < example.txt 
Hello World # may also be empty

Das Problem ist, dass der > example.txt(oder im dd of=example.txtÜbrigen) die Datei beendet, bevor der andere Prozess die Möglichkeit hat, sie zu lesen. Es gibt also keine offensichtliche Lösung, weshalb Sie sich an diese halten sollten mv.

Es gibt eine Reihe von Möglichkeiten, wie Sie betrügen können. Sie können die Datei öffnen, dann die Verknüpfung aufheben - die Datei bleibt bestehen, bis Sie sie schließen - und dann eine neue Datei mit demselben Namen erstellen und die komprimierten Daten in diese Datei schreiben. Ich kenne jedoch keinen offensichtlichen Weg, Bash dazu zu zwingen, und selbst wenn ich es tun würde, wäre meine Antwort immer noch:

Tu es nicht einmal.

Wenn gzipaus irgendeinem Grund ein Fehler auftritt oder ein Problem auftritt, z. B. wenn Ihnen beim Gzippen der Speicherplatz ausgeht (weil andere Prozesse schreiben oder das Gzip-Ergebnis größer ist als die Eingabe - was bei zufälligen Daten der Fall ist - usw.), haben Sie einfach Ihre Datei verloren . Herzliche Glückwünsche!

Erstellen Sie eine separate Datei und mvbei Erfolg. Dies ist die einfachste, verständlichste und zuverlässigste Methode, die Sie jemals finden werden.

Frostschutz
quelle
1
Wie wäre es der Vollständigkeit halber mit dem Hinzufügen von:gzip example.txt && mv example.txt.gz example.txt
depquid
2
Kein Depquid hat das OP gelesen - das ist unelegant .
Goldlöckchen
@goldilocks "Erstellen Sie eine separate Datei und mvbei Erfolg." kann eleganter gemacht werden? Ich wollte nur vorschlagen, dass die Antwort von frostschutz durch ein konkretes Beispiel ergänzt wird. Wenn mveleganter verwendet werden kann, als ich dachte, geben Sie bitte ein Beispiel.
depquid
Ihr Vorschlag ist der einfache, elegante, offensichtliche Ansatz, aber ob er funktioniert, hängt von so vielen Variablen ab, z. B. was tun Sie, wenn es bereits eine example.txt.gz gibt? Auch ohne Erweiterung, mit der Sie arbeiten können, müssen Sie verhindern, dass bereits gzippte Dateien irgendwie gzippt werden. Das ist eine ganz neue Dose Würmer, aber das war nicht wirklich Teil der Frage.
Frostschutz
10

Ich hatte das gleiche Problem im Rahmen einer CI-Bereitstellung für AWS S3.

Dies ist, was ich getan habe, um ein Verzeichnis (an Ort und Stelle) ohne das .gzSuffix rekursiv zu gzippen :

find . -type f -exec gzip "{}" \; -exec mv "{}.gz" "{}" \;

Scheint mir sauber genug zu sein. Aber ja, es sieht so aus, als ob Sie mvirgendwo eine brauchen .

Wenn Sie verwenden, können gruntSie sich anschauen grunt-contrib-compress. Einige der gruntTools, die speziell für die Bereitstellung auf S3 entwickelt wurden, übernehmen auch gzip für Sie.

tobek
quelle
1
sollte das Leerzeichen bitte find . -type ...nicht find.hinzufügen :)
Humdinger
2

-S Erweiterung, die Sie möchten

gzip -S "`_date +%Y_%M' dog.txt 

führt zu dog.txt_2015_11

Wenn Sie es entpacken, müssen Sie die Erweiterung angeben.

gzip -d _2015_11 dog.txt_2015_11

Verwenden Sie unter Unix den Befehl file, um festzustellen, über welchen Dateityp Sie verfügen, welche Erweiterungen irreführend sind oder häufig fehlen.

user143758
quelle
1

Ich denke nicht, dass das Erstellen einer gzip-Datei ohne Erweiterung wirklich das Richtige ist.

IMHo sollten Sie Ihren Webserver so konfigurieren, dass er die .gz-Datei liest. Sie haben wahrscheinlich bereits eine Regel wie diese:

Path asets/:
  If header Accept-Encoding contains "gzip" and not contains "gzip;q=0":
    Add header Content-Encoding: gzip

Sie müssen lediglich eine Regel hinzufügen, die den angeforderten Dateinamen umschreibt, um ".gz" anzufügen (tatsächlich sollten Sie überprüfen, ob die Datei vorhanden ist, genauso wie Sie überprüfen sollten, ob der Client gzip in seinem Accept-Encoding-Header aufgeführt hat).

Engel
quelle
1

Sie können s3_website dafür ausprobieren .

Mir gefällt nicht, dass es sowohl in Scala als auch in Ruby geschrieben ist und eine JVM benötigt. Ich mag auch die Annahme nicht (insbesondere die Tatsache, dass zusätzliche Dateien aus dem Bucket gelöscht werden), aber es sollte funktionieren, wenn Sie damit einverstanden sind.

Ich habe vor, ein solches Tool selbst zu schreiben, das diese Einschränkungen nicht aufweist. Bleiben Sie dran.

Cristian Măgherușan-Stanciu
quelle
0

Dies sollten Sie eigentlich nicht tun, vor allem, wenn Sie diese Datei auf andere Systeme oder Personen übertragen, kann dies zu Verwirrung führen und dazu, dass Sie sie nicht als komprimierte Datei finden.

Wenn Sie kein Suffix verwenden möchten, ist GNU nicht gut für Sie, da es a zurückgeben gzip -S ""würde gzip: invalid suffix ''.

Sie können jedoch immer so etwas wie gzip -S " "(Leerzeichen) senden , und es wird wie folgt angezeigt:

$ file testfile\  
testfile: gzip compressed data, was "testfile", from Unix, last modified: Tue Jun  3 XX:XX:XX 2014

Wenn Sie es anschließend dekomprimieren möchten, müssen Sie etwas wie gunzip -c testfile\ (ohne Angabe des Suffix) oder sogar mit -fflag ausführen.

Ich bin der festen Überzeugung, dass das Hinzufügen eines mvBefehls mit &&nicht zu einem großen Ärger für Ihren Code führen würde. Wie auch immer, und wie @frostschutz gesagt hat, ist es keine wirklich gute Idee, dies zu tun.

AleksanderKseniya
quelle
Dies ist erforderlich, wenn Sie S3 zum Bereitstellen komprimierter Dateien verwenden möchten, z. B. zum Hosten einer statischen Website. Dies könnte Sie interessieren
Cristian Măgherușan-Stanciu