Я хочу удалить все файлы без следующих расширений, а также файлы без расширения в каталоге в Linux.
Ответ 2
Вы можете использовать быструю и грязную команду rm
для выполнения того, что вы хотите, но имейте в виду, что она подвержена ошибкам, не переносима, опасна и имеет серьезные ограничения.
Как и другие, вы можете использовать команду find
. Я бы рекомендовал использовать find
, а не rm
почти во всех случаях.
Поскольку вы упоминаете, что находитесь в системе Linux, я буду использовать реализацию GNU, которая является частью пакета findutils в моих примерах, потому что он по умолчанию используется для большинства систем Linux и является тем, что я обычно рекомендую для обучения, поскольку он имеет гораздо более богатый и расширенный набор функций, чем многие другие реализации.
Хотя это может быть сложным и, казалось бы, чрезмерно сложным, стоит потратить время на овладение командой find
, потому что это дает вам определенную выразительность и безопасность, которые вы не найдете с большинством других методов без по существу (плохо ) повторно изобретать эту команду!
Найти пример
Люди часто предлагают использовать команду find
в неэффективных, подверженных ошибкам и опасных способах, поэтому ниже я излагаю безопасный и эффективный способ, чтобы выполнить именно то, что вы спросил в вашем примере.
Перед удалением файлов я рекомендую сначала просмотреть список файлов (или, по крайней мере, часть списка, если он очень длинный):
find path/to/files -type f -regextype posix-extended -iregex '.*\.(avi|mkv|wmv|mp4|mp5|flv|M4V|mpeg|mov|m1v|m2v|3gp|avchd)$'
Вышеуказанная команда покажет вам список файлов, которые вы будете удалять. Чтобы фактически удалить файлы, вы можете просто добавить действие -delete
следующим образом:
find path/to/files -type f -regextype posix-extended -iregex '.*\.(avi|mkv|wmv|mp4|mp5|flv|M4V|mpeg|mov|m1v|m2v|3gp|avchd)$' -delete
Если вы хотите посмотреть, что останется, вы можете инвертировать совпадения в предварительном просмотре, добавив !
в команду предварительного просмотра ( без -delete
) следующим образом:
find path/to/files -type f -regextype posix-extended ! -iregex '.*\.(avi|mkv|wmv|mp4|mp5|flv|M4V|mpeg|mov|m1v|m2v|3gp|avchd)$'
Результат этого обратного совпадения должен быть таким же, как вывод, который вы увидите при перечислении файлов после выполнения удаления, если ошибки не возникли из-за проблем с разрешениями или невоспроизводимых файловых систем:
find path/to/files -type f
Описание
Здесь я подробно объясню варианты, которые я выбрал и почему:
Я добавил -type f
в ограничение совпадений только с файлами; без этого он будет соответствовать нефайлам, таким как каталоги, которые вы, вероятно, не хотите. Также обратите внимание, что я помещаю его в начале, а не в конец, потому что порядок предикатов может иметь значение для скорости; с -type f
сначала он выполнит проверку регулярных выражений против файлов, а не против всего... на практике это может не иметь большого значения, если у вас нет большого количества каталогов или нефайлов. Тем не менее, стоит учесть порядок предикатов, поскольку в некоторых случаях это может оказать значительное влияние.
Я использую параметр без учета регистра -iregex
в отличие от параметра -regex
, учитывающего регистр, потому что я предположил, что вы хотите использовать нечувствительность к регистру, поэтому он будет включать в себя как .wmv
и .wmv
.
Вы, вероятно, захотите использовать расширение регулярных выражений POSIX для простоты и краткости. К сожалению, для -regextype posix-extended
пока нет короткой руки, но даже я бы рекомендовал использовать его, потому что вы можете избежать проблемы добавления большого количества обратных косых черт \
, чтобы избежать вещей в более длинных и более сложных регулярных выражениях. более современные (современные) функции. Реализация GNU по умолчанию соответствует emges-style regexes, которая может сбивать с толку, если вы не привыкли к ним.
Опция -delete
должна иметь очевидный смысл, однако иногда люди предлагают использовать более медленный и более сложный вариант -exec rm {} \;
, но обычно это потому, что они не знают о более безопасной, быстрой и простой опции -delete
( и в редких случаях вы можете столкнуться с старыми системами с древней версией find
, у которой нет этой опции). Полезно знать, что существует -exec
, но используйте -delete
, где вы можете удалить файлы. Кроме того, не выгружайте |
вывод find
в другую программу, если вы не используете и не понимаете опцию -print0
, иначе вы находитесь в мире обид, когда вы сталкиваетесь с файлами с пробелами.
Аргумент path/to/files
я включил явно. Если вы оставите его, он косвенно будет использовать .
в качестве пути, однако безопаснее (особенно с -delete
) явно указывать путь.
Альтернативный поиск Реализации
Даже если вы сказали, что находитесь в системе Linux, я также расскажу о различиях, с которыми вы столкнетесь с BSD-реализациями, в которых включает Mac OS X! Для других систем (например, более старых ящиков Solaris) удачи! Обновите один из более современных вариантов find
!
Основное различие в этом примере касается регулярных выражений. Варианты BSD по умолчанию используют стандартные регулярные выражения POSIX. Чтобы избежать обременительного дополнительного ускорения в регулярных выражениях, требуемых для basic-PRE, вы можете воспользоваться более современными функциями расширенного PRE, указав опцию -E
с вариантом BSD для достижения того же поведения, что и вариант GNU, который использует -regextype posix-extended
.
find -E path/to/files -iregex '.*\.(avi|mkv|wmv|mp4|mp5|flv|M4V|mpeg|mov|m1v|m2v|3gp|avchd)$' -type f
Обратите внимание, что в этом случае параметр -E
поставляется до path/to/files
, тогда как опция -regextype posix-extended
для GNU имеет после путь.
Плохо, что GNU еще не предоставил параметр -E
(пока!); так как я думаю, что было бы полезным вариантом иметь четность с вариантами BSD, я отправлю патч на findutils
, чтобы добавить эту опцию, и если она будет принята, я буду соответствующим образом обновлять этот ответ.
rm - не рекомендуется
Хотя я настоятельно рекомендую использовать rm
, я приведу примеры того, как более или менее точно задать ваш вопрос (с некоторыми оговорками).
Предполагая, что вы используете оболочку с синтаксисом Bourne (обычно это то, что вы найдете в системе Linux, которая по умолчанию используется для оболочки Bash), вы можете использовать эту команду:
for ext in avi mkv wmv mp4 mp5 flv M4V mpeg mov m1v m2v 3gp avchd; do rm -f path/to/files/*.$ext; done
Если вы используете Bash и включили расширенное включение с помощью shopt -s extglob
, вы можете использовать Соответствие шаблону с расширением файла:
rm -f path/to/files/*.+(avi|mkv|wmv|mp4|mp5|flv|M4V|mpeg|mov|m1v|m2v|3gp|avchd)
Синтаксис расширенного синтаксиса +(pattern-list)
будет соответствовать одному или нескольким вхождениям данных шаблонов.
Однако я настоятельно рекомендую использовать rm
, потому что:
Он подвержен ошибкам и опасен, потому что легко случайно помещать пробел между *
, что означает, что вы удалите все; вы не можете предварительно просмотреть результат команды раньше времени; это огонь и забыть, так что удачи с последствиями.
Он не переносится, потому что даже если он работает в вашей конкретной оболочке, такая же командная строка может не работать в других оболочках (включая другие варианты Bourne-shell, если вы склонны к использованию Bash -измы).
У этого есть серьезные ограничения, потому что если у вас есть файлы, которые вложены в подкаталоги или даже очень много файлов в одном каталоге, то вы быстро достигнете пределов длины командной строки при использовании файлового глобирования.
Мне хотелось бы, чтобы команда rm
просто зашла в небытие rm
, потому что я могу думать о нескольких местах, где я предпочитаю использовать rm
вместо (даже древних реализаций) find
.