Подтвердить что ты не робот

Удалить все файлы, которые не имеют следующих расширений в Linux

У меня есть список расширений:

avi,mkv,wmv,mp4,mp5,flv,M4V,mpeg,mov,m1v,m2v,3gp,avchd

Я хочу удалить все файлы без следующих расширений, а также файлы без расширения в каталоге в Linux.

Как это сделать, используя команду rm linux?

4b9b3361

Ответ 1

Сначала вам нужно будет найти файлы, которые не содержат эти расширения. Вы можете сделать это очень легко с помощью команды find. Вы можете построить следующую команду:

find /path/to/files ! -name "*.avi" -type f -exec rm -i {} \;

Вы также можете использовать -regex вместо -name для комбинирования в сложном шаблоне поиска. ! означает отрицание поиска. Таким образом, он будет эффективно перечислять те файлы, которые не содержат эти расширения.

Хорошо сделать rm -i, поскольку перед удалением будет отображаться все файлы. Это может стать утомительным, если ваш список является исчерпывающим, поэтому вы можете решить, включить его или нет.

Удаление тонны файлов с использованием этого параметра может быть опасно. После удаления вы никогда не сможете вернуть их. Поэтому убедитесь, что вы запустили команду find без rm, чтобы сначала проверить список перед удалением.

Update:

Как указано в комментариях aculich, вы также можете сделать следующее -

find /path/to/files ! -name "*.avi" -type f -delete

-type f гарантирует, что он будет только find и delete обычных файлов и не будет касаться каких-либо каталогов, сим-ссылок и т.д..

Ответ 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.

Ответ 3

С помощью Bash вы можете сначала включить опцию extglob:

$shopt -s extglob

И сделайте следующее:

$rm -i! (*. avi | *.mkv | *.wmv | *.mp4)