Ви можете використовувати 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). (наголос мій)