🧹 Удаление всех файлов в директории, кроме определённых расширений

Когда нужно очистить каталог от лишних файлов, сохранив только файлы определённых типов, Linux предлагает несколько способов сделать это быстро из терминала. Рассмотрим три метода: расширенные шаблоны (опция Bash extglob), утилиту find и переменную Bash GLOBIGNORE – расскажем, как работает каждый, приведём пример команды и подскажем, когда какой способ удобнее использовать.
⚠️ Внимание: Будьте осторожны с командами удаления. Рекомендуется сначала протестировать их без удаления (например, через echo или в безопасной директории) либо использовать опцию -i для подтверждения каждого файла, чтобы не потерять нужные данные.
✨ Способ 1: Расширенные шаблоны Bash (extglob)
Этот метод использует встроенную возможность Bash для расширенного сопоставления шаблонов. С помощью специального шаблона !(pattern) можно задать маску, которая означает «всё, что не соответствует указанному шаблону». Для начала необходимо включить поддержку extglob в текущем Shell:
shopt -s extglob # включаем расширенные шаблоны
Теперь можно применять шаблон ! при удалении. Например, чтобы удалить все файлы, кроме файлов с расширениями .zip и .odt в текущем каталоге:
rm -v !(*.zip|*.odt)
Эта команда удалит все файлы, имеющие другие расширения, кроме .zip и .odt. Выражение !(*.zip|*.odt) означает «любое имя, которое не оканчивается на .zip или .odt». Флаг -v в команде rm включён для наглядности – утилита перечислит имена удалённых файлов в выводе.
После выполнения уборки не забудьте отключить режим extglob, если он больше не нужен:
shopt -u extglob # отключаем расширенные шаблоны
Когда использовать: Метод с extglob удобен для быстрого удаления файлов в одном каталоге из интерактивного Bash. Он хорошо подходит, когда нужно исключить от удаления один-два известных типа файлов. Учтите, что предварительно придётся включить опцию extglob. Для рекурсивного удаления по подкаталогам или при очень большом числе файлов (когда шаблон может развернуться в слишком длинный список аргументов) лучше выбрать другой подход.
🔎 Способ 2: Утилита find
Вместо возможностей оболочки можно воспользоваться утилитой find, которая ищет файлы по критериям и может выполнять над ними действия. Этот способ не требует специальных настроек Shell и подходит для более сложных случаев.
Чтобы удалить все файлы, кроме определённого типа, find позволяет отфильтровать имена по шаблону. Используем параметр -not -name (или ! -name). Например, команда ниже удалит все файлы, кроме файлов с расширением .gz (gzip-архивов) в текущем каталоге и во всех его подкаталогах:
find . -type f -not -name "*.gz" -delete
Аргумент -type f ограничивает поиск только обычными файлами (исключая каталоги), а условие -not -name "*.gz" отсекает файлы, чьи имена оканчиваются на .gz. Опция -delete приказывает сразу удалить найденные файлы.
Если нужно сохранить несколько разных расширений, можно указать несколько условий или объединить их логическим OR. К примеру, следующая команда удалит всё, кроме файлов с расширениями .gz и .odt:
find . -type f -not \( -name "*.gz" -o -name "*.odt" \) -delete
Здесь конструкция \( ... -o ... \) группирует условия: -name "*.gz" OR -name "*.odt". Обратные слэши перед скобками нужны, чтобы избежать их интерпретации самим Shell. Таким образом, удалению подвергнутся все файлы, не удовлетворяющие ни одному из шаблонов (то есть не .gz и не .odt).
Когда использовать: find — мощный инструмент, особенно полезный для рекурсивного удаления в глубоко вложенных структурах каталогов. Его стоит выбирать, если нужно пройтись по подкаталогам автоматически или когда файлов очень много. Кроме того, find не зависит от конкретной оболочки — команда сразу готова к работе в любом скрипте или терминале. При необходимости можно добавить параметр -maxdepth 1, чтобы ограничить поиск только текущим каталогом (без рекурсии), или использовать связку с xargs для дополнительного контроля (например, чтобы вывести список удаляемых файлов перед удалением через -print0 | xargs -0 -I{} rm -v {}).
⚙️ Способ 3: Переменная GLOBIGNORE (Bash)
Последний подход работает только в Bash и основан на встроенной переменной окружения GLOBIGNORE, которая задаёт шаблоны файлов, игнорируемые при расширении глобальных масок (*, ? и т.д.). Проще говоря, мы можем заранее указать оболочке, какие имена исключить из рассмотрения, а затем удалить всё остальное обычной командой.
Сначала перейдите в нужный каталог:
cd /path/to/dir
Установите переменную GLOBIGNORE, перечислив через двоеточие шаблоны файлов, которые нужно сохранить. Например, чтобы не трогать файлы с расширениями .odt, .iso и .txt:
GLOBIGNORE=*.odt:*.iso:*.txt
Теперь выполните удаление всех файлов с помощью маски *:
rm -v *
Команда rm -v * удалит все файлы в текущем каталоге, кроме тех, что соответствуют шаблонам в переменной GLOBIGNORE (то есть кроме файлов с расширениями .odt, .iso, .txt). Ключ -v позволяет увидеть, какие именно файлы были удалены в процессе. После очистки каталога желательно сбросить значение переменной, чтобы вернуть обычное поведение shell:
unset GLOBIGNORE
Когда использовать: Приём с GLOBIGNORE полезен, если вы работаете в Bash и хотите быстро удалить всё лишнее, указав список исключений «что оставить». Он удобен для одноразовой очистки текущего каталога без написания длинных команд. Однако помните, что этот способ специфичен для Bash и не будет работать в других оболочках. В скриптах или для массового удаления по системе его используют редко; в таких случаях надёжнее прибегнуть к find или аналогичным утилитам.


