gzip все файлы с определенными расширениями

9

Я пытаюсь gzip все файлы на ubuntu, которые имеют расширение файла .css, .html или .js. в верхнем каталоге и во всех подкаталогах. Я хочу сохранить исходные файлы и перезаписать файл .gz, если он уже существует.

Итак, когда у меня есть n файлов, я хочу сохранить эти n файлов и создать дополнительные n архивных файлов. Не только один.

Моя попытка состояла в том, чтобы запустить скрипт, который выглядит так:

gzip -rkf *.css
gzip -rkf *.html
... one line for each file extension

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

Второе и более важное: это не работает. Хотя -r должен выполнять задание, подкаталоги не изменяются. Файл gzip создается только в верхнем каталоге.

Что мне здесь не хватает?

Btw: Ниже приведена ошибка в подробном выводе, правильно? При использовании опции -k и -v

-k, --keep        keep (don't delete) input files
-v, --verbose     verbose mode

В подробном выводе говорится, что он заменяет файл, хотя «replace» означает, что исходный файл не существует после замены. Во всяком случае, это только выходная информация.

$ 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
    
задан Sadik 11.07.2014 в 11:58
источник

6 ответов

7

вы можете сделать это с помощью цикла for, чтобы найти каждый файл, а затем сжать его:

for i in 'find | grep -E "\.css$|\.html$"'; do gzip "$i" ; done
    
ответ дан mndo 11.07.2014 в 12:09
источник
10

Я бы использовал

find /path/to/dir \( -name '*.css' -o -name '*.html' \) -exec gzip --verbose --keep {} \;

Измените name на iname , если вы хотите совпадать с расширениями без учета регистра (т. е. включить .CSS и / или .HTML расширений). Вы можете опустить /path/to/dir , если хотите начать рекурсивный поиск из текущего каталога.     

ответ дан steeldriver 11.07.2014 в 12:24
4

Чтобы получить список файлов:

find -type f | grep -P '\.js|\.html|\.css'

И для gzip всех этих файлов:

find -type f | grep -P '\.js|\.html|\.css' | tar cvzf archive.gz -T -
    
ответ дан chaos 11.07.2014 в 12:11
2

Я использовал ответ steeldriver , но мне нравится заполнить его с помощью опций --best и --force .

cd в любую папку и введите этот код. Все ваши соответствующие файлы будут скопированы.

find . \( -name '*.css' -o -name '*.js' \) -exec gzip --verbose --keep --best --force {} \;
  • Используйте --best для лучшей степени сжатия.
  • Используйте --force для перезаписи, не спрашивая, есть ли файл gzipped.
ответ дан azerafati 27.02.2015 в 09:14
1

Вы можете использовать globstar.

При включенной опции оболочки globstar все, что вам нужно, это gzip -vk **/*.{css,html} .

У оболочки Bash есть опция globstar , которая позволяет писать рекурсивную < href="https://www.gnu.org/software/bash/manual/bash.html#Pattern-Matching"> globs с ** . shopt -s globstar позволяет. Но вы можете не захотеть этого делать для других команд, которые вы запускаете позже, поэтому вы можете запустить его и команду gzip в подселе вместо этого.

Эта команда gzip s всех .css и .html файлов в текущем каталоге любого из ее подкаталогов, любого из их подкаталогов и т. д., сохраняя исходные файлы ( -k ) и сообщая вам, что он делает ( -v ):

(shopt -s globstar; gzip -vk **/*.{css,html})

Если вы хотите совместить имена файлов с учетом регистра, так что эти расширения с некоторыми или всеми заглавными буквами включены, вы также можете включить опцию nocaseglob :

(shopt -s globstar nocaseglob; gzip -vk **/*.{css,html})

; разделяет две команды, а внешний ( ) заставляет их запускаться в подоболочке. Установка опции оболочки в подоболочке не приводит к ее установке в вызывающей оболочке. Если вы do хотите включить globstar , вы можете запустить shopt -s globstar ; то вы можете просто запустить команду:

gzip -vk **/*.{css,html}

Вы можете отключить globstar с shopt -u globstar . Вы можете проверить, включено ли в настоящее время с помощью shopt globstar .

Как это работает

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

  • Расширение брекета превращает **/*.{css,html} в **/*.css **/*.html .
  • Затем globbing расширяет эти два шаблона в имена файлов, доступных в текущий каталог ( ** , из-за globstar ), имена файлов которого состоят из всего ( * ), за которым следует указанный суффикс ( .css или .html в этом случае).

Это не соответствует файлам, имена которых начинаются с . или тех, которые находятся в каталогах с именем сюда. У вас, вероятно, нет таких файлов HTML и CSS, и если вы это сделаете, вы, вероятно, не захотите их включать. Но если вы хотите включить их, то вы можете их явно сопоставить в зависимости от ваших потребностей. Например, изменение **/*.{css,html} до **/{,.}*.{css,html} включает файлы, которые начинаются с . , в то время как not выполняется поиск в папках, которые делают.

Если вы хотите, чтобы оба файла, чьи имена начинались с . и файлы в каталогах, чьи имена начинаются с . , должны быть включены, есть более чистый и простой способ: включите опцию оболочки dotglob .

(shopt -s globstar dotglob; gzip -vk **/*.{css,html})

Или если вы хотите совпадение без учета регистра и совпадения имен файлов, начинающихся с . :

(shopt -s globstar nocaseglob dotglob; gzip -vk **/*.{css,html})

Возможно, хотя очень редко, для ** для расширения слишком долго.

Если у вас есть число огромных файлов с таким именем, это может привести к ошибке с сообщением об ошибке, объясняющим, что оболочка не может построить командную строку, потому что она слишком длинная. (Даже с тысячами файлов этот обычно не является проблемой.)

gzip не будет вызываться вообще, поэтому вы не получите задание, сделанное на половину.

Если эта ошибка произошла или вы беспокоитесь об этом, вы можете использовать find с -exec , либо как steeldriver описывает {} \; ) или как описано ниже (с {} + ).

Вы можете использовать find с действием -exec и + для эффективности.

Команда gzip поддерживает имена нескольких сжатых файлов. Но эта команда find , хотя она работает хорошо и не будет медленной, если у вас нет файлов many , запускается команда gzip для файла each :

find . \( -name \*.css -o -name \*.html \) -exec gzip -vk {} \;

Это работает, и вы можете определенно использовать его. ( . ищет из текущего каталога. Кроме того, это действительно немного другой способ написания команды в очень хороший steeldriver answer , вы можете использовать любой стиль, который вы предпочитаете.)

Вы также можете сделать find передать несколько имен файлов в gzip и запустить его столько раз, сколько необходимо - это почти всегда один раз. Для этого используйте + вместо \; . Аргумент + должен появиться сразу после {} . find заменяет + дополнительными именами файлов, если они есть.

find . \( -name \*.css -o -name \*.html \) -exec gzip -vk {} +

Хорошо использовать + , даже если есть только несколько совпадающих файлов, а когда их много, это может быть заметно быстрее, чем наличие отдельного вызова gzip для каждого файла.

Как указатель steeldriver , вы можете использовать -iname вместо -name для соответствия файлам, конец которых равен .css или .html , но с другой капитализацией. Это соответствует включению nocaseglob в методе globstar , описанном выше.

Наконец, у вас, вероятно, нет соответствующих файлов или каталогов, начинающихся с . . Но если вы это сделаете, find автоматически включит их. Если вы хотите исключить их (как это происходит с методом globstar , описанным выше, когда dotglob выключено), вы можете :

find . -not -path '*/.*' \( -name \*.css -o -name \*.html \) -exec gzip -vk {} +

Способ, описанный выше на globstar , проще писать, особенно если вы исключаете каталоги и файлы, начинающиеся с . , поскольку это значение по умолчанию.

Что не делать ...

Имена файлов могут содержать любой символ, кроме разделителя путей / , и нулевой символ . Существует много методов, которые ломаются над странными именами файлов, и они обычно сложнее , чем методы, которые всегда работают. Поэтому я предлагаю избегать их, даже когда вы знаете (или думаете, что знаете), они в порядке с вашей конкретной ситуацией. И, конечно же, вы должны не использовать их, если у вас могут быть имена файлов с особенностями, которые могут быть обработаны специально, включая пробелы.

Можно безопасно передать вывод find другой команде, которая обрабатывает ее , если вы используете -print0 или подобное действие, чтобы заставить его поместить нулевой символ между путями вместо новой строки , а не иначе. Имена файлов могут содержать символы новой строки (хотя я отговариваю вас от намеренного именования файлов с ними). Команда find с действием -print - включая команды поиска без явного действия, так как тогда -print по умолчанию - не выводит вывод, который можно безопасно передать или иным образом передать другой команде, которая выполняет действие на файлах.

Результат find , выражающийся с действием -print0 , может быть безопасно передан в xargs -0 (флаг -0 сообщает xargs , чтобы ожидать ввода с нулевым разделением).

    
ответ дан Eliah Kagan 14.08.2017 в 15:04
0

Чтобы автоматически перепечатать все файлы в папке / подпапке:

gzip -r 'find . -type f -name "*.html"' 

Чтобы распаковать:

gunzip -r 'find . -type f -name "*.gz"' 
    
ответ дан Naruto_Hokage 15.09.2016 в 19:42