Как создать файл gzip без расширения файла .gz?

14

Я хотел бы создать сжатый файл, который сохраняет оригинальное имя файла. Например, при распаковке «example.txt» должен быть распакован файл с именем «example.txt», а не «example.txt.gz». Можно ли сделать это элегантно с помощью одной команды (без последующей mv)?

jamieb
источник
4
Мне немного любопытно. Почему вы хотите этого? Это звучит как плохая идея.
Бернхард
3
Да. Вы помещаете две целые строки в скрипт bash и называете это "my-элегантная команда". ;)
Златовласка
2
@Bernhard Это часть процесса непрерывной интеграции веб-приложения. Статические ресурсы (файлы CSS, JS) необходимо сжимать без изменения имени файла. При доставке в браузер включается заголовок «content-encoding: gzip», поэтому расширение не имеет значения. Но если имя файла изменилось, я должен выполнить поиск и замену в исходных файлах HTML.
jamieb
Если это действительно большая проблема для вас, вы можете определить функцию bash, которая передает $ * исполняемому файлу gzip, а вторая строка делает mv для вас.
Братчли
4
@ Твоя проблема с веб-приложением: любой достойный веб-сервер может / сделает сжатие за тебя ...
Bananguin

Ответы:

12

Это не работает:

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

Это условие гонки:

# 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

Проблема в том, что > example.txt(или dd of=example.txtв этом отношении) убивает файл, прежде чем другой процесс сможет его прочитать. Так что нет очевидного решения, поэтому вы должны придерживаться mv.

Есть несколько способов обмануть. Вы можете открыть файл, затем отсоединить его - файл будет существовать до тех пор, пока вы его не закроете, - а затем создать новый файл с тем же именем и записать в него сжатые данные. Однако я не знаю очевидного способа заставить bash использовать это, и даже если бы я знал, мой ответ все равно будет:

Даже не делай этого.

Если gzipпо какой-либо причине происходит сбой или возникает какая-либо проблема, например, когда у вас не хватает места во время gzipping (потому что другие процессы пишут, или результат gzip больше, чем ввод - что происходит для случайных данных - и т. Д.), Вы просто потеряли свой файл , Поздравляем!

Создайте отдельный файл и mvв случае успеха. Это самый простой, легкий для понимания и самый надежный метод, который вы когда-либо найдете.

frostschutz
источник
1
Как насчет добавления ради полноты:gzip example.txt && mv example.txt.gz example.txt
depquid
2
Никакой depquid не читает OP - это не элегантно .
Златовласка
@goldilocks "Создайте отдельный файл и mvв случае успеха." можно сделать более элегантным? Я просто пытался предложить, чтобы ответ Фростшуца был дополнен конкретным примером. Если mvможно использовать более элегантно, чем я думал, приведите пример.
depquid
Ваше предложение - простой, элегантный, очевидный подход, но работает ли он, зависит от очень многих переменных, например, что вы будете делать, если уже есть файл example.txt.gz? Также без расширения для работы, вы должны каким-то образом предотвратить сжатие уже сжатых файлов. Это новая банка червей, но это не было частью вопроса.
frostschutz
10

У меня была такая же проблема, как часть развертывания CI на AWS S3.

Это то, что я сделал для рекурсивного сжатия каталога (на месте) без .gzсуффикса:

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

Кажется достаточно чистым для меня. Но да, похоже, тебе нужно mvгде-то там.

Если вы используете, gruntвы можете посмотреть grunt-contrib-compress. Некоторые gruntинструменты, специально предназначенные для развертывания на S3, также будут работать с gzip.

tobek
источник
1
следует find . -type ...не find.добавлять пространство , пожалуйста :)
вещица
2

-S расширение, которое вы хотите

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

приведет к dog.txt_2015_11

когда вы распаковываете его, вы должны указать расширение.

gzip -d _2015_11 dog.txt_2015_11

В Unix используйте команду file, чтобы определить, какой тип файла у вас, расширения вводят в заблуждение или часто отсутствуют.

user143758
источник
1

Я не думаю, что создание gzip-файла без расширения - действительно правильная вещь.

IMHo вы должны настроить свой веб-сервер для чтения файла .gz. У вас, вероятно, уже есть такое правило:

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

Вам просто нужно добавить правило, переписывающее запрашиваемое имя файла, чтобы добавить «.gz» (на самом деле, вы должны убедиться, что файл существует, точно так же, как вы должны убедиться, что клиент перечислил gzip в заголовке Accept-Encoding)

Анхель
источник
1

Вы можете попробовать s3_website для этого.

Мне не нравится тот факт, что он написан на scala и ruby, и что ему нужна JVM. Также мне не нравится предположение, которое он делает (особенно тот факт, что он удаляет дополнительные файлы из корзины), но оно должно работать, если вы хорошо с этим.

Я планирую написать такой инструмент самостоятельно, который не имеет этих ограничений, следите за обновлениями.

Кристиан Магерушан-Станчу
источник
0

Это на самом деле не то, что вам следует делать, в основном потому, что при передаче этого файла другим системам или людям он может запутаться и не найти его в виде сжатого файла.

Если вы не хотите использовать какой-либо суффикс, тогда GNU не подходит для вас, так как gzip -S ""возвращает a gzip: invalid suffix ''.

Тем не менее, вы всегда можете отправить что-то вроде gzip -S " "(пробел), и это будет показано так:

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

Впоследствии, если вы хотите распаковать его, вам нужно будет сделать что-то вроде gunzip -c testfile\ (без указания суффикса) или даже с -fфлагом.

Я искренне думаю, что добавление mvкоманды с помощью &&не будет так хлопотно для вашего кода. В любом случае, как сказал @frostschutz, это не очень хорошая идея.

AleksanderKseniya
источник
Это то, что нужно, если вы хотите использовать S3 для обслуживания сжатых файлов, например, для размещения статического веб-сайта. Вы можете подумать об этом: github.com/laurilehmijoki/s3_website
Кристиан Магерушан-Станчу