У меня есть список расширений:
avi,mkv,wmv,mp4,mp5,flv,M4V,mpeg,mov,m1v,m2v,3gp,avchd
Я хочу удалить все файлы без следующих расширений, а также файлы без расширения в каталоге в Linux.
Как это сделать, используя команду rm linux?
У меня есть список расширений:
avi,mkv,wmv,mp4,mp5,flv,M4V,mpeg,mov,m1v,m2v,3gp,avchd
Я хочу удалить все файлы без следующих расширений, а также файлы без расширения в каталоге в Linux.
Как это сделать, используя команду rm linux?
Сначала вам нужно будет найти файлы, которые не содержат эти расширения. Вы можете сделать это очень легко с помощью команды 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
обычных файлов и не будет касаться каких-либо каталогов, сим-ссылок и т.д..
Вы можете использовать быструю и грязную команду 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
, я приведу примеры того, как более или менее точно задать ваш вопрос (с некоторыми оговорками).
Предполагая, что вы используете оболочку с синтаксисом 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
.
С помощью Bash вы можете сначала включить опцию extglob:
$shopt -s extglob
И сделайте следующее:
$rm -i! (*. avi | *.mkv | *.wmv | *.mp4)