
Я хотел бы удалить все файлы txt, xls, pdf в каталоге, а также его подкаталоги. Я хотел бы сохранить все остальное.
find . -type f ! -iname '*.xml$,.png$,.jpeg$,.gif$,' -delete
это, казалось, сделало это, но это удалило некоторые другие файлы, которые мне нужны. Как я могу добиться этого, не удаляя ничего другого?
решение1
Вместо этого сделайте следующее:
find . -type f -iname '*.xml' -o -iname '*.png'\
-o -iname '*.jpeg' -o -iname '*.gif' -delete
Вы также можете использовать регулярные выражения:
find . -type f -iregex '.*\.\(xml\|png\|jpeg\|gif\)$' -delete
решение2
По сути, существует 4 способа решения этой проблемы с помощью find.
Метод №1 - использование-delete
$ find . -type f -iname '*.xml' -o -iname '*.png'\
-o -iname '*.jpeg' -o -iname '*.gif' -delete
Как уже упоминалось в этом разделе вопросов и ответов, этот метод является самым быстрым и наименее ресурсоемким. Цитата изнайти онлайн-документы:
10.1.6 Использование действия `-delete'
Наиболее эффективным и безопасным методом решения этой проблемы является использование действия `-delete':
find /var/tmp/stuff -mtime +90 -delete
Эта альтернатива более эффективна, чем любое из
-exec' or
действий -execdir', поскольку она полностью избегает накладных расходов на разветвление нового процесса и использованиеexec' to run
/bin/rm'. Она также обычно более эффективна, чемxargs' for the same reason. The file deletion is performed from the directory containing the entry to be deleted, so the
действие -delete', имеет те же преимущества безопасности, что и действие `-execdir'.Действие `-delete' было введено семейством операционных систем BSD.
ПРИМЕЧАНИЕ:При таком подходе следует помнить об одном: использование -delete
подразумевает также переключатель -depth
. Что это значит? Вот пример того, как -delete
можно обжечься, если не быть осторожным.
Например, скажем, у меня есть рабочий каталог subversion, в котором я хочу очистить некоторые файлы, но оставить его подкаталоги .svn нетронутыми. Я могу использовать следующую команду, чтобы сделать это:
$ find . -not "(" -name .svn -type d -prune ")" -type f -print
./a.txt
Но поскольку -delete
включает -depth
переключатель, файлы, которые фактически будут обрабатываться:
$ find . -not "(" -name .svn -type d -prune ")" -type f -print -depth
./.svn/all-wcprops
./.svn/entries
./.svn/format
./.svn/text-base/a.txt.svn-base
./a.txt
По этой причине при использовании -delete
необходимо соблюдать осторожность.
Метод №2 --exec command {} +
$ find . -type f -iname '*.xml' -o -iname '*.png'\
-o -iname '*.jpeg' -o -iname '*.gif' -exec rm {} \+
По сравнению с -delete
методом, это, скорее всего, следующий лучший вариант с точки зрения производительности и переносимости между Unix. Нотация -exec ... {} +
работает следующим образом:
из страницы поиска руководства
Этот вариант действия -exec запускает указанную команду для выбранных файлов, но командная строка создается путем добавления каждого выбранного имени файла в конец; общее количество вызовов команды будет намного меньше количества соответствующих файлов. Командная строка создается примерно так же, как xargs создает свои командные строки. В команде допускается только один экземпляр `{}'. Команда выполняется в начальном каталоге.
Таким образом, по сути, этот метод работает аналогично xargs
, но без необходимости преодолевать препятствия, передавая вывод find через конвейер в xargs
.
Метод №3 -xargs
$ find . -type f -iname '*.xml' -o -iname '*.png'\
-o -iname '*.jpeg' -o -iname '*.gif' -print0 | xargs -0 rm -f
Будет find ... -print0
создан список файлов, соответствующих указанным критериям. Затем этот список передается по каналу в xargs
. -print0
Переключатель помещает символ ASCII NUL в качестве разделителя между каждым результатом поиска. -0
Переключатель on xargs
предполагает, что передаваемые файлы разделены символами ASCII NUL.
По сравнению со способами № 1 и № 2 этот метод будет иметь производительность, аналогичную способу № 2, однако этот -print0
переключатель не поддерживается всеми Unix-системами.
Метод №4 --exec command {} \;
$ find . -type f -iname '*.xml' -o -iname '*.png'\
-o -iname '*.jpeg' -o -iname '*.gif' | exec rm -f {} \;
По сравнению с первыми тремя методами, этот наименее производительный. Он буквально вызывает команду rm
для каждого отдельного файла, который find
команда находит.
Дополнительные соображения по поводу безопасности
Одна вещь, которая может быть не столь очевидной при использовании любого из вышеперечисленных методов, заключается в том, что некоторые из методов более безопасны, чем другие. Вы, вероятно, говорите себе: ... безопасность? .. что? Вот пример.
Предположим, что вы являетесь пользователем root и выполняете следующую команду:
$ find /var/tmp/somedir -type f -exec rm {} \;
Без вашего ведома кто-то злонамеренно создал ссылку на /etc
каталог в /var/tmp/somedir
. При запуске указанной выше команды /etc
каталог также будет удален. Эта проблема существует при любом из методов удаления файлов, за исключением варианта -delete
(метод № 1).
вкратце;
Самый быстрый и безопасный способ удалить файлы с помощью find — использовать -delete
. Использование xargs -0
может быть схожим по производительности, но не таким безопасным. -delete
Действие не является полностью переносимым. Наиболее эффективной переносимой альтернативой является -exec ... +
, но это небезопасно и не поддерживается версиями GNU findutils до 4.2.12.
Рекомендации
решение3
Есть небольшая неточностьответ слм.
ПРИМЕЧАНИЕ и отказ от ответственности: это должен быть комментарий кответ слмно сейчас я пока не могу комментировать.
Пример «кто-то злонамеренно создал ссылку», приведенный вДополнительные соображения по поводу безопасностине совсем точен как в отношении жестких ссылок Unix, так и в отношении мягких ссылок Unix.
Чтобы понять разницу между ними, см.Жесткие ссылки и символические ссылки в Unixили погуглите.
Для мягких ссылок (самый используемый тип) GNU find
иBDS find
неследовать символическим ссылкам, если не используется специальный -L
флаг для принудительного следования по символической ссылке. [См. man find
]
Так что этот пример, скорее всего, не будет проблемой, если только высила find
следовать по мягким ссылкам с использованием -L
флага. Это опасный выбор, в любом случае.
Для жестких ссылок, find
будет следовать ссылке надругой файлно учтите, что жесткая ссылка надругой каталог«вероятно, потерпит неудачу», как показано в примере man ln
для GNU ln
:
-d, -F, --directory
allow the superuser to attempt to hard link directories (note: will probably
fail due to system restrictions, even for the superuser)
Поэтому, скорее всего, изначально невозможно создать жесткую ссылку на каталог, и по ней find
не будет ничего, за чем можно было бы следить.
Обратите внимание, что некоторые реализации BDS вообще ln
не имеют такой возможности.-d