Вы можете использовать Globstar.
С globstar
включенной опцией оболочки все, что вам нужно, это gzip -vk **/*.{css,html}
.
Bash оболочка имеет globstar
опцию , которая позволяет писать рекурсивные шарики с **
. shopt -s globstar
позволяет это. Но вы, возможно, не захотите делать это для других команд, которые вы запускаете позже, поэтому вместо этого вы можете запустить его и свою gzip
команду в подоболочке .
Эта команда хранит gzip
все .css
и .html
файлы в текущем каталоге, любые его подкаталоги, любые их подкаталоги и т. Д., Сохраняя исходные файлы ( -k
) и сообщая вам, что она делает ( -v
):
(shopt -s globstar; gzip -vk **/*.{css,html})
Если вы хотите сопоставлять имена файлов без учета регистра, чтобы включить эти расширения с несколькими или всеми заглавными буквами, то вы также можете включить параметр nocaseglob
оболочки:
(shopt -s globstar nocaseglob; gzip -vk **/*.{css,html})
;
разделяет две команды, и внешняя (
)
причина их запуска в подоболочке. Установка параметра оболочки в подоболочке не приводит к его установке в вызывающей оболочке. Если вы действительно хотите включить , globstar
то вы можете запустить shopt -s globstar
; тогда вы можете просто запустить команду:
gzip -vk **/*.{css,html}
Вы можете отключить globstar
с помощью shopt -u globstar
. Вы можете проверить, включен ли он в данный момент shopt globstar
.
Как это устроено
Ключом к тому, как gzip
работает эта команда, является то, что оболочка выполняет над ней расширение для создания списка каждого файла в иерархии каталогов с соответствующим именем, а затем передает каждое из этих имен файлов в качестве аргументов gzip
.
- Расширение скобки превращается
**/*.{css,html}
в **/*.css **/*.html
.
- Затем глобализация расширяет эти два шаблона в имена файлов, доступных в текущем каталоге (
**
из-за globstar
), имена файлов которых состоят из чего-либо ( *
), за которым следует указанный суффикс ( .css
или .html
в этом случае).
Это не соответствует файлам, чьи имена начинаются с.
тех, которые находятся в каталогах, названных таким образом. Вероятно, у вас нет таких файлов HTML и CSS, и, если у вас есть, вы, вероятно, не хотите их включать. Но если вы хотите включить их, то вы можете явно сопоставить их в зависимости от ваших потребностей. Например, переход **/*.{css,html}
на **/{,.}*.{css,html}
включаемые файлы, которые начинаются с поиска, .
но по-прежнему не выполняется поиск в папках.
Если вы хотите, чтобы включались и файлы, имена которых начинаются с, .
и файлы в каталогах, имена которых начинаются с .
, есть более простой и понятный способ: включите параметр 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
команда, хотя она работает хорошо и не будет медленной, если у вас много файлов, запускает gzip
команду один раз для каждого файла:
find . \( -name \*.css -o -name \*.html \) -exec gzip -vk {} \;
Это работает, и вы определенно можете его использовать. ( .
выполняет поиск в текущем каталоге. Кроме того, это действительно немного другой способ написания команды в очень хорошем ответе Steeldriver ; вы можете использовать любой стиль, который вы предпочитаете.)
Вы также можете find
передать несколько имен файлов gzip
и запускать их только столько раз, сколько необходимо - что почти всегда только один раз. Для этого используйте +
вместо\;
. +
Аргумент должен прийти только после того, как {}
. find
заменяет +
дополнительные имена файлов, если таковые имеются.
find . \( -name \*.css -o -name \*.html \) -exec gzip -vk {} +
Его можно использовать, +
даже если есть только несколько подходящих файлов, и когда их много, это может быть заметно быстрее, чем отдельный gzip
вызов для каждого файла.
Как упоминает Steeldriver , вы можете использовать -iname
вместо того, -name
чтобы сопоставлять файлы, имена которых заканчиваются на .css
или, .html
но с другой прописной буквой . Это соответствует включению nocaseglob
в globstar
основанном на методе, описанном выше.
Наконец, у вас, вероятно, нет соответствующих файлов или каталогов, которые начинаются с .
. Но если вы делаете, find
автоматически включает их. Если вы хотите исключить их (как это происходит с globstar
методом -base, подробно описанным выше, когда dotglob
он выключен), вы можете :
find . -not -path '*/.*' \( -name \*.css -o -name \*.html \) -exec gzip -vk {} +
globstar
Основанное способ , описанный выше, проще писать, особенно если вы за исключением каталогов и файлов , которые начинаются с .
, так как это по умолчанию.
Что не надо делать ...
Имена файлов могут содержать любой символ, кроме разделителя пути /
и нулевого символа . Существует много техник, которые ломают странные имена файлов, и они обычно более сложны, чем техники, которые всегда работают. Поэтому я предлагаю избегать их, даже если вы знаете (или думаете, что знаете), что они в вашей конкретной ситуации. И, конечно, вы не должны использовать их, если у вас могут быть имена файлов с символами, которые могут обрабатываться особым образом, включая пробелы.
Можно безопасно передать вывод find
другой команды, которая ее обрабатывает, если вы используете -print0
или подобное действие, чтобы заставить его помещать нулевой символ между путями вместо новой строки , и не иначе. Имена файлов могут содержать символы новой строки (хотя я не рекомендую вам сознательно именовать файлы вместе с ними). find
Команда с -print
действием - включая команды найти без каких - либо явных действий, так как то -print
по умолчанию - не производит вывод , который можно безопасно свирель или иной не предусмотрен в другую команду , которая выполняет действие на файлах.
Результат, find
полученный с -print0
действием, может быть безопасно передан по каналу xargs -0
( -0
флаг указывает xargs
ожидать ввода с нулевым разделением).
-r
работает как задумано. От man gzip : рекурсивно путешествовать по структуре каталогов. Если какое-либо из имен файлов, указанных в командной строке, является каталогом , gzip спустится в каталог и сожмет все найденные там файлы (или распакует их в случае gunzip). (выделение мое)