Мне нужно удалить все файлы с расширением .gif, кроме одного файла с именем сказать «filename.gif». Каков оптимальный способ сделать это в терминале?
Команда rm *.gif
удаляет все gif-файлы, включая файл filename.gif
.
источник
Мне нужно удалить все файлы с расширением .gif, кроме одного файла с именем сказать «filename.gif». Каков оптимальный способ сделать это в терминале?
Команда rm *.gif
удаляет все gif-файлы, включая файл filename.gif
.
Вот простое решение, которое вы, вероятно, должны использовать:
mv filename.gif filename.gif.keep
rm *.gif
mv filename.gif.keep filename.gif
В .keep
расширении нет ничего особенного , это просто делает так, чтобы имя файла временно не заканчивалось .gif
.
Если вы не должны переименовать файл (и есть скриптовые ситуации , когда это важно):
for X in *.gif; do
if [ "$X" != "filename.gif" ]; then
rm "$X"
fi
done
Или вы можете написать это короче, как это:
for X in *.gif; do [ "$X" != "filename.gif" ] && rm "$X"; done
Вы можете предпочесть использовать find
вместо этого; он очень мощный, вы можете считать его более читабельным и лучше обрабатывать странные имена файлов с такими же символами, как *
в них .
find . -maxdepth 1 -not -name 'filename.gif' -name '*.gif' -delete
Я использовал -not
оператор для удобочитаемости, но если важно соответствие POSIX - если вы не используете GNU find, или это для сценария, который вы собираетесь распространять среди других, или запускать на различных системах - вам следует используйте !
вместо этого оператор:
find . -maxdepth 1 ! -name 'filename.gif' -name '*.gif' -delete
Одна полезная вещь в find
том, что вы можете легко изменить команду для учета регистра, чтобы она находила и удаляла файлы с такими расширениями, как .GIF
тоже:
find . -maxdepth 1 -not -name 'filename.gif' -iname '*.gif' -delete
Обратите внимание, что я использовал -iname
вместо -name
шаблона поиска, *.gif
но я не использовал его для filename.gif
. Предположительно, вы точно знаете, как называется ваш файл, и -iname
будут совпадать с заглавными буквами не только в расширении , но и в любом месте имени файла.
Все эти решения удаляют только файлы, находящиеся непосредственно в текущем каталоге . Они не удаляют файлы, не содержащиеся в текущем каталоге, и не удаляют файлы, которые находятся в подкаталогах текущего каталога.
Если вы хотите удалить файлы везде, содержащиеся в текущем каталоге (то есть в подкаталогах и в подкаталогах этих подкаталогов и т. Д. - файлы, содержащиеся в текущем каталоге или любом из его потомков), используйте find
без maxdepth -1
:
find . -not -name 'filename.gif' -name '*.gif' -delete
Будьте осторожны с этим!
Вы также можете установить другие значения с помощью -maxdepth
. Например, чтобы удалить файлы в текущем каталоге и его дочерних элементах и внуках, но не глубже:
find . -maxdepth 3 -not -name 'filename.gif' -name '*.gif' -delete
Просто убедитесь, что вы никогда не ставите на -delete
первое место, прежде чем другие выражения! Вы увидите, я всегда ставлю -delete
в конце. Если вы поместите его в начале, он будет оценен первым, и все файлы в нем .
(включая файлы, не оканчивающиеся на .gif
и файлы в глубоких подподчиненных ... каталогах .
) будут удалены!
Для получения дополнительной информации обратитесь к страницам справочника bash
и sh
и для команд , используемых в этих примерах: mv
, rm
, [
, и (особенно) find
.
find
, который очень универсален.find
это действительно хорошая находка.find
обрабатывать странные имена файлов,*
чем в цикле for? Цикл for*
хорошо обрабатывает файлы , потому что вы использовали двойные кавычки.Если вы используете
bash
(оболочка по умолчанию),extglob
опция оболочки позволяет вам использовать расширенный синтаксис сопоставления с образцом. Чтобы включить его, используйтеshopt
встроенную команду:(Я включил эту строку в мой
.bashrc
файл.)Помимо прочего, он предоставляет доступ к
!()
оператору, который соответствует любому шаблону, не входящему в состав скобок. Для вашей цели:Более подробная информация доступна в
man bash
разделе «Сопоставление с образцом».источник
extglob
должна быть включена, но ничего плохого не произойдет, если он отключен (в этом случае это просто не работает). И, кажется, он включен по умолчанию, хотя у меня нет ниshopt -s extglob
одного из моих (или глобальных) файлов конфигурации. Если есть простое объяснение того, почему это работает для меня из коробки, вы можете добавить его к этому ответу; или я могу опубликовать новый вопрос.Откройте терминал с помощью Ctrl+ Alt+ Tи введите:
Разница между
-delete
и-exec rm -vf {} \;
заключается в том, что со вторым параметром вы сможете увидеть, какие файлы были удалены из-за-v
флага. Это то, что не может быть сделано с-delete
опцией. (-name -delete
напечатает имена файлов, ноrm
с-v
показом, если каждый файл был успешно удален.)источник
Там
GLOBIGNORE
переменная. Отman bash
:Итак, простой способ - просто указать
GLOBGINORE
имя файла, о котором идет речь:Итак, в вашем случае:
Конечно, поскольку он
GLOBIGNORE
содержит шаблоны, вы можете использовать его, когда хотите исключить шаблон:(?!) Преимуществом
GLOBIGNORE
является то , что установка автоматически исключает.
и..
от подкрепляются, и это позволяетdotglob
:Итак, простой способ удаления всех файлов и папок в каталоге:
*
Будет соответствовать имена файлов , начинающиеся с.
, так какGLOBIGNORE
включенdotglob
, но он не будет соответствовать.
или..
, так что вы не будет влиять на родительский каталог , что путь.источник