Ви можете використовувати 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 {} \;
Це працює, і ви точно можете ним скористатися. ( .
пошук із поточного каталогу. Крім того, це дійсно дещо інший спосіб написання команди в дуже гарній відповіді ; ви можете використовувати будь-який стиль, який ви бажаєте.)
Ви також можете 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
очікувати введення, розділеного на нуль).
-r
працює як задумано. Від man gzip : Подорожуйте структуру каталогу рекурсивно. Якщо будь-яке з імен файлів, вказаних у командному рядку, є каталогами , gzip зійде в каталог і стисне всі файли, які він там знайде (або розпакує їх у випадку gunzip). (наголос мій)