Я пытаюсь сжать все файлы в Ubuntu, которые имеют расширение .css, .html или .js. в верхнем каталоге и во всех подкаталогах. Я хочу сохранить исходные файлы и перезаписать файл .gz, если он уже существует.
Поэтому, когда у меня есть n файлов, я хочу сохранить эти n файлов и создать дополнительные n архивных файлов. Не только один.
Я попытался запустить скрипт, который выглядит следующим образом:
gzip -rkf *.css
gzip -rkf *.html
... one line for each file extension
Во-первых: мне нужно иметь одну строку в этом скрипте для каждого расширения файла, которое я хочу сжать. Это нормально, но я надеюсь найти лучший способ
Второе и более важное: это не работает. Хотя -r должен выполнить эту работу, подкаталоги не изменились. Файл gzip создается только в верхнем каталоге.
Что мне здесь не хватает?
Кстати: ниже приведена ошибка в подробном выводе, верно? При использовании параметров -k и -v
-k, --keep keep (don't delete) input files
-v, --verbose verbose mode
В подробном выводе говорится, что он заменяет файл, хотя «замена» означает, что исходный файл не существует после замены. Во всяком случае, это только выходная вещь.
$ 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
-r
работает как задумано. От man gzip : рекурсивно путешествовать по структуре каталогов. Если какое-либо из имен файлов, указанных в командной строке, является каталогом , gzip спустится в каталог и сожмет все найденные там файлы (или распакует их в случае gunzip). (выделение мое)Ответы:
Вы можете сделать это с помощью цикла for, чтобы найти каждый файл и затем сжать его:
источник
-r
опция не работает-k
и-f
работает, поэтому я могу использовать их следующим образом: для я вfind | grep -E "\.css$|\.html$"
; do gzip -vkf "$ i"; done``...`
предоставляет строку, а не список.for
использует внутренний разделитель полей ($IFS
), чтобы решить, где должна быть разбита эта строка. По умолчанию он разделяется на переводы строк, табуляции и пробелы, поэтому, если у вас есть файл с именемnew style.css
, командыgzip new
иgzip style.css
будут выполнены.export IFS=$'\n'
непосредственно передfor
циклом.я хотел бы использовать
Измените
name
на,iname
если вы хотите сопоставлять расширения без учета регистра (т.е. включать.CSS
и / или.HTML
расширения). Вы можете опустить,/path/to/dir
если вы хотите начать рекурсивный поиск из текущего каталога.источник
--keep
переключателем, да, это приводит к сохранению исходных файлов. Опустите его, если вы хотите, чтобы они были удалены после gzip.Чтобы получить список файлов:
И сжать все эти файлы:
источник
tar
find
-T
опциейtar
обрабатывает ввод как имена файлов.Я использовал ответ steeldriver в , но я хотел бы завершить его с
--best
и--force
опциями.cd
в любую папку и введите этот код. Все ваши соответствующие файлы будут сжаты.--best
для лучшей степени сжатия.--force
для перезаписи, не спрашивая, есть ли уже сжатый файл.источник
Вы можете использовать Globstar.
С
globstar
включенной опцией оболочки все, что вам нужно, этоgzip -vk **/*.{css,html}
.Bash оболочка имеет
globstar
опцию , которая позволяет писать рекурсивные шарики с**
.shopt -s globstar
позволяет это. Но вы, возможно, не захотите делать это для других команд, которые вы запускаете позже, поэтому вместо этого вы можете запустить его и своюgzip
команду в подоболочке .Эта команда хранит
gzip
все.css
и.html
файлы в текущем каталоге, любые его подкаталоги, любые их подкаталоги и т. Д., Сохраняя исходные файлы (-k
) и сообщая вам, что она делает (-v
):Если вы хотите сопоставлять имена файлов без учета регистра, чтобы включить эти расширения с несколькими или всеми заглавными буквами, то вы также можете включить параметр
nocaseglob
оболочки:;
разделяет две команды, и внешняя(
)
причина их запуска в подоболочке. Установка параметра оболочки в подоболочке не приводит к его установке в вызывающей оболочке. Если вы действительно хотите включить ,globstar
то вы можете запуститьshopt -s globstar
; тогда вы можете просто запустить команду:Вы можете отключить
globstar
с помощьюshopt -u globstar
. Вы можете проверить, включен ли он в данный моментshopt globstar
.Как это устроено
Ключом к тому, как
gzip
работает эта команда, является то, что оболочка выполняет над ней расширение для создания списка каждого файла в иерархии каталогов с соответствующим именем, а затем передает каждое из этих имен файлов в качестве аргументовgzip
.**/*.{css,html}
в**/*.css **/*.html
.**
из-заglobstar
), имена файлов которых состоят из чего-либо (*
), за которым следует указанный суффикс (.css
или.html
в этом случае).Это не соответствует файлам, чьи имена начинаются с
.
тех, которые находятся в каталогах, названных таким образом. Вероятно, у вас нет таких файлов HTML и CSS, и, если у вас есть, вы, вероятно, не хотите их включать. Но если вы хотите включить их, то вы можете явно сопоставить их в зависимости от ваших потребностей. Например, переход**/*.{css,html}
на**/{,.}*.{css,html}
включаемые файлы, которые начинаются с поиска,.
но по-прежнему не выполняется поиск в папках.Если вы хотите, чтобы включались и файлы, имена которых начинаются с,
.
и файлы в каталогах, имена которых начинаются с.
, есть более простой и понятный способ: включите параметрdotglob
оболочки.Или, если вы хотите, чтобы регистронезависимое совпадение и совпадение имен файлов начиналось с
.
:Возможно, хотя и очень редко,
**
расширяться до чего-то слишком длинного.Если у вас есть огромное количество файлов, названных таким образом, это может привести к ошибке с сообщением об ошибке, объясняющим, что оболочка не может создать командную строку, потому что она будет слишком длинной. (Даже с тысячами файлов это обычно не проблема.)
gzip
не будет вызван вообще, так что вы не получите наполовину выполненную работу.Если эта ошибка происходит, или если вы беспокоитесь об этом, вы можете использовать
find
с-exec
, либо как steeldriver описывает (с{} \;
) или как я опишу ниже (с{} +
).Вы можете использовать
find
с-exec
действием и+
для эффективности.Команда
gzip
поддерживает задание имен нескольких файлов для сжатия. Но этаfind
команда, хотя она работает хорошо и не будет медленной, если у вас много файлов, запускаетgzip
команду один раз для каждого файла:Это работает, и вы определенно можете его использовать. (
.
выполняет поиск в текущем каталоге. Кроме того, это действительно немного другой способ написания команды в очень хорошем ответе Steeldriver ; вы можете использовать любой стиль, который вы предпочитаете.)Вы также можете
find
передать несколько имен файловgzip
и запускать их только столько раз, сколько необходимо - что почти всегда только один раз. Для этого используйте+
вместо\;
.+
Аргумент должен прийти только после того, как{}
.find
заменяет+
дополнительные имена файлов, если таковые имеются.Его можно использовать,
+
даже если есть только несколько подходящих файлов, и когда их много, это может быть заметно быстрее, чем отдельныйgzip
вызов для каждого файла.Как упоминает Steeldriver , вы можете использовать
-iname
вместо того,-name
чтобы сопоставлять файлы, имена которых заканчиваются на.css
или,.html
но с другой прописной буквой . Это соответствует включениюnocaseglob
вglobstar
основанном на методе, описанном выше.Наконец, у вас, вероятно, нет соответствующих файлов или каталогов, которые начинаются с
.
. Но если вы делаете,find
автоматически включает их. Если вы хотите исключить их (как это происходит сglobstar
методом -base, подробно описанным выше, когдаdotglob
он выключен), вы можете :globstar
Основанное способ , описанный выше, проще писать, особенно если вы за исключением каталогов и файлов , которые начинаются с.
, так как это по умолчанию.Что не надо делать ...
Имена файлов могут содержать любой символ, кроме разделителя пути
/
и нулевого символа . Существует много техник, которые ломают странные имена файлов, и они обычно более сложны, чем техники, которые всегда работают. Поэтому я предлагаю избегать их, даже если вы знаете (или думаете, что знаете), что они в вашей конкретной ситуации. И, конечно, вы не должны использовать их, если у вас могут быть имена файлов с символами, которые могут обрабатываться особым образом, включая пробелы.Можно безопасно передать вывод
find
другой команды, которая ее обрабатывает, если вы используете-print0
или подобное действие, чтобы заставить его помещать нулевой символ между путями вместо новой строки , и не иначе. Имена файлов могут содержать символы новой строки (хотя я не рекомендую вам сознательно именовать файлы вместе с ними).find
Команда с-print
действием - включая команды найти без каких - либо явных действий, так как то-print
по умолчанию - не производит вывод , который можно безопасно свирель или иной не предусмотрен в другую команду , которая выполняет действие на файлах.Результат,
find
полученный с-print0
действием, может быть безопасно передан по каналуxargs -0
(-0
флаг указываетxargs
ожидать ввода с нулевым разделением).источник
Чтобы рекурсивно сжать все файлы в папке / подпапке:
Разархивировать:
источник
`
`
синтаксиса, но проблема полностью применима и при использовании$(
)
синтаксиса.)