Comment créer un fichier gzip sans extension de fichier .gz?

14

Je voudrais créer un fichier gzippé qui conserve le nom du fichier d'origine. Par exemple, gzipping "example.txt" devrait générer un fichier gzippé nommé "example.txt" plutôt que "example.txt.gz". Est-il possible de le faire avec élégance avec une seule commande (sans faire de commande ultérieure mv)?

jamieb
la source
4
Je suis un peu curieux. Pourquoi vous voulez ceci? Cela ressemble à une mauvaise idée.
Bernhard
3
Ouais. Vous mettez 2 lignes entières dans un script bash et vous l'appelez "ma-commande-élégante". ;)
goldilocks
2
@Bernhard Cela fait partie d'un processus de construction d'intégration continue pour une application Web. Les actifs statiques (fichiers CSS, JS) doivent être compressés sans changer le nom du fichier. Lorsqu'il est remis au navigateur, un en-tête "content-encoding: gzip" est inclus, de sorte que l'extension n'est pas pertinente. Mais si le nom de fichier est changé, je dois faire une recherche et remplacer dans les fichiers HTML source.
jamieb
Si c'est vraiment un gros problème pour vous, vous pouvez définir une fonction bash qui passe $ * à l'exécutable gzip et la deuxième ligne fait le mv pour vous.
Bratchley
4
@votre problème d'application web: n'importe quel serveur web décent peut / fera la compression pour vous ...
Bananguin

Réponses:

12

Cela ne fonctionne pas:

# 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>

Il s'agit d'une condition de concurrence:

# 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

Le problème est que le > example.txt(ou dd of=example.txtd'ailleurs) tue le fichier avant que l'autre processus ait la chance de le lire. Il n'y a donc pas de solution évidente, c'est pourquoi vous devez vous y tenir mv.

Il existe plusieurs façons de tricher. Vous pouvez ouvrir le fichier, puis le dissocier - le fichier continuera d'exister jusqu'à ce que vous le fermiez - puis créer un nouveau fichier avec le même nom et y écrire les données compressées. Cependant, je ne connais pas de moyen évident de contraindre bash à l'utiliser, et même si je le faisais, ma réponse serait toujours:

Ne le fais même pas.

Si gzipéchoue pour une raison quelconque ou si un problème survient, comme si vous manquez d'espace pendant le gzipping (parce que d'autres processus sont en train d'écrire ou si le résultat de gzip est plus grand que l'entrée - ce qui se produit pour les données aléatoires - etc.), vous venez de perdre votre fichier . Toutes nos félicitations!

Créez un fichier séparé et mven cas de succès. C'est la méthode la plus simple, facile à comprendre et la plus fiable que vous trouverez jamais.

frostschutz
la source
1
Que diriez-vous d'ajouter par souci d'exhaustivité:gzip example.txt && mv example.txt.gz example.txt
depquid
2
Aucun depquid n'a lu l'OP - c'est inélégant .
goldilocks
@goldilocks "Créez un fichier séparé et mven cas de succès." peut être rendu plus élégant? J'essayais simplement de proposer que la réponse de frostschutz soit complétée par un exemple spécifique. Si vous mvpouvez l'utiliser plus élégamment que je ne le pensais, veuillez donner un exemple.
depquid
Votre suggestion est l'approche simple, élégante et évidente, mais son efficacité dépend de tant de variables, par exemple, que faites-vous s'il existe déjà un exemple.txt.gz? De plus, sans extension avec laquelle travailler, vous devez empêcher de compresser les fichiers déjà compressés. C'est une toute nouvelle boîte de vers, mais cela ne faisait pas vraiment partie de la question.
frostschutz
10

J'ai eu le même problème, dans le cadre d'un déploiement CI sur AWS S3.

Voici ce que j'ai fait pour compresser récursivement un répertoire (en place) sans le .gzsuffixe:

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

Semble assez propre pour moi. Mais oui, on dirait que vous en avez besoin mvquelque part.

Si vous utilisez, gruntvous pouvez regarder grunt-contrib-compress. Certains des gruntoutils spécifiquement destinés au déploiement sur S3 géreront également gzip pour vous.

tobek
la source
1
ne devrait find . -type ...pas find.ajouter l'espace s'il vous plaît :)
Humdinger
2

-S extension que vous voulez

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

résultera en dog.txt_2015_11

lorsque vous le décompressez, vous devez spécifier l'extension.

gzip -d _2015_11 dog.txt_2015_11

Sous Unix, utilisez la commande file pour déterminer le type de fichier dont vous disposez, les extensions sont trompeuses ou manquent souvent.

user143758
la source
1

Je ne pense pas que la création d'un fichier gzip sans extension soit vraiment la bonne chose à faire.

IMHo vous devez configurer votre serveur web pour lire le fichier .gz. Vous avez probablement déjà une règle comme celle-ci:

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

Vous avez juste besoin d'ajouter une règle réécrivant le nom de fichier demandé pour ajouter ".gz" (en fait, vous devez vérifier que le fichier existe, tout comme vous devriez vérifier que le client a bien répertorié gzip sur son en-tête Accept-Encoding)

Ange
la source
1

Vous pouvez essayer s3_website pour cela.

Je n'aime pas le fait qu'il soit écrit en scala et en rubis et qu'il nécessite une machine virtuelle Java. De plus, je n'aime pas l'hypothèse qu'il fait (en particulier le fait qu'il supprime des fichiers supplémentaires du compartiment), mais cela devrait fonctionner si cela vous convient.

Je prévois d'écrire un tel outil par moi-même qui n'a pas ces limitations, restez à l'écoute.

Cristian Măgherușan-Stanciu
la source
0

Ce n'est pas vraiment quelque chose que vous devriez faire, principalement parce que lors du transfert de ce fichier vers d'autres systèmes ou personnes, cela pourrait être source de confusion pour eux et ne pas le trouver en tant que fichier compressé.

Si vous ne voulez pas utiliser de suffixe, alors GNU n'est pas bon pour vous, comme gzip -S ""retournerait a gzip: invalid suffix ''.

Cependant, vous pouvez toujours envoyer quelque chose comme gzip -S " "(espace vide), et il sera affiché comme ceci:

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

Ensuite, si vous voulez le décompresser, vous devrez faire quelque chose comme gunzip -c testfile\ (sans spécifier le suffixe), ou même avec -fflag.

Je pense sincèrement que l'ajout d'une mvcommande avec &&ne compliquerait pas beaucoup votre code. Quoi qu'il en soit, et comme l'a dit @frostschutz, ce n'est pas vraiment une bonne idée de le faire.

AleksanderKseniya
la source
C'est quelque chose qui est nécessaire si vous souhaitez utiliser S3 pour servir des fichiers compressés, comme pour héberger un site Web statique. Vous pourriez considérer ceci: github.com/laurilehmijoki/s3_website
Cristian Măgherușan-Stanciu