Недавно я столкнулся с задачей удаления всех файлов / папок в каталоге, кроме тех, которые соответствуют определенному шаблону. Поэтому я подготовил однострочную команду Unix для выполнения этой работы. Это должна быть только одна строка? Полагаю, нет, но это определенно круче!
Хотя проблема довольно проста, я был немного удивлен тем, насколько сложным оказалось мое решение. Вот команда, которую я использовал; ПРИМЕЧАНИЕ: это плохое решение, потому что оно не обрабатывает имена файлов, содержащие символы перевода строки (что не имело значения в моей ситуации).
ls | grep -v PATTERN | xargs -n1 -IREPLACE rm -rf REPLACE
Я не использовал команду «найти», потому что я не хочу копировать в папки, соответствующие PATTERN. Например, рассмотрим следующую файловую структуру:
file_foo.txt
first_dir
|
+--> contents
+--> ...
foo_dir
|
+--> anotherfile.txt
+--> morefiles.log
foo_file.txt
somefile.txt
При использовании шаблона "foo" необходимо удалить только "first_dir" (и, конечно, его содержимое) и "somefile.txt" ( не "anotherfile.txt" или "morefiles.log").
Вопрос, есть ли лучшие (более элегантные и правильные) способы сделать это?
РЕДАКТИРОВАТЬ:
Недавно было доведено до моего сведения, что «найти» может быть лучшим вариантом:
find * -maxdepth 0 ! -name PATTERN -print0 | xargs -0n1 rm -rf
Это решение правильно обрабатывает пути, содержащие символы перевода строки.
источник
Ответы:
Следующие примеры имеют
echo
префикс, так что вы можете проверить шаблоны перед их фактическим использованием. Удалить,echo
чтобы активироватьrm -rf
. Заменить,rm -ri
чтобы запросить подтверждение.ksh имеет расширение с отрицательным соответствием для его смещения:
Тот же синтаксис доступен в bash, если вы установите
extglob
опцию:У zsh есть собственный синтаксис для этого:
Он также может использовать синтаксис стиля ksh :
источник
shopt -s extglob
в мой файл .bashrc, так что теперь он является однострочным). Отлично! Я обещаю поднять голос, как только моя репутация позволяет это.Вот еще одно
find
решение. Я не уверен, что это имеет какое-то реальное преимущество перед вашим, но это не нужноxargs
и учитывает редкую возможность, * расширяющуюся до слишком большого количества имен.Я также добавил,
-type f
что он не будет пытаться удалить каталоги.Предупреждение:
-delete
это мощно. Я дал одному из моих тестовых файлов 0 разрешений, и команда выше удалила его без колебаний.источник
-delete
на,-print
чтобы увидеть, находит ли он нужные вам файлы. Если все хорошо, используйте историю команд (например, нажмите кнопку вверх), чтобы вернуться к предыдущей команде, чтобы убедиться, что вы работаете с теми же фильтрами поиска.find -delete
не удалит непустые каталоги. Также обратите внимание, чтоfind -maxdepth 1
соответствует "." (текущий каталог), что действительно плохо. Хотя мне нравится ваша идея устраненияxargs
, можно использоватьfind -exec
альтернативно.find * -maxdepth 0 ! -name PATTERN -exec rm -rf '{}' \;
Вместо этого вы можете использовать этот пример сценария реболя http://askcodegeneration.com/keep-subversion/, который гораздо более понятен и может управлять взаимодействием с пользователем, таким как выбор и подтверждение папки:
источник