Есть 2 способа прочитать этот вопрос, и существующие ответы охватывают обе интерпретации: ЛИБО: (а) сохраняйте файлы с указанными именами, непосредственно расположенные в целевом каталоге, и - как это rm -rподразумевается - удаляйте все остальное, включая подкаталоги, - даже если они содержат файлы с указанными именами; ИЛИ: (b) пройти по всему поддереву целевого каталога и в каждом каталоге удалить все файлы, кроме файлов с именами в списке.
mklement0
Ответы:
219
find [path]-type f -not -name 'textfile.txt'-not -name 'backup.tar.gz'-delete
Если вы не укажете, -type ffind также выведет список каталогов, которые вам могут не понадобиться.
Или более общее решение с использованием очень полезной комбинации find | xargs:
Когда я это делаю, я получаю "синтаксическую ошибку рядом с неожиданным токеном` ('" shopt -s extglob; rm -rf !(README|LICENSE). Есть идеи почему?"
Денис
@ nnic Я не помню, извини. Я, вероятно, в конечном итоге использовать findс -deleteопцией.
Деннис
Это лучшее решение для меня, и оно работает по умолчанию на моей Ubuntu 12.04.4 LTS без необходимости покупки
xtian
3
@nic, @Dennis: синтаксическая ошибка предполагает, что что-то ДРУГОЕ, чем bashбыло использовано, например dash, где extglobне поддерживается. Однако в интерактивнойbash оболочке команда также не будет работать, как указано, хотя и по другим причинам. Суть в том, чтобы выполнить себя shopt -s extglob; РАЗ УСПЕШНО ВКЛЮЧЕНО (проверьте с помощью shopt extglob), выполните rm -rf !(README|LICENSE). (Хотя extglobон еще не включен, !(...)оценивается расширением истории ДО того, как команды будут выполнены; поскольку это, скорее всего, не сработает, команда NEITHER будет выполнена и extglobникогда не будет
включена
2
@nic, @Dennis, @ mklement0: у меня была та же проблема с «синтаксической ошибкой рядом с неожиданным токеном» (при выполнении команды в файле .sh (#! / bin / bash), но не при запуске его в команде . Линейный интерфейс оказалось, что в дополнение к shopt -s extglobперспективе в интерфейсе командной строки, я должен был повторно его в свой файл сценария Это решило проблему для меня..
При этом будут перечислены все файлы в текущем каталоге, затем перечислены все те, которые не соответствуют вашим критериям (остерегайтесь совпадения с именами каталогов), а затем удалите их.
Обновление : на основе ваших правок, если вы действительно хотите удалить все из текущего каталога, кроме файлов, которые вы перечислили, это можно использовать:
Это создаст резервную копию каталога /tmp_backup(у вас есть права root, верно?), Переместит файлы, которые вы перечислили в этот каталог, рекурсивно удалите все в текущем каталоге (вы знаете, что вы находитесь в правильном каталоге, не так ли?), Переместите вернуться к текущему каталогу все /tmp_backupи, наконец, удалить /tmp_backup.
Я выбираю каталог резервного копирования в качестве корневого, потому что если вы пытаетесь рекурсивно удалить все из корневого каталога, у вашей системы будут большие проблемы.
Конечно, есть более элегантные способы сделать это, но этот довольно простой.
Также очень хорошо работает с egrep, например, для очистки промежуточных латексных файлов:find . | egrep -v "\.tex|\.bib" | xargs rm
mtsz
потрясающая команда! для удаления каталогов просто измените на rm -r
Aris
1
Если вы хотите просто удалить все в текущем каталоге, кроме исключенных критериев: find . -maxdepth 1 | grep -v "exclude these" | xargs rm -rработает намного быстрее, так как не нужно детализировать каталоги без необходимости.
Биллиноа
Повторный findконвейер: проблемы эффективности в стороне (3 команды используются для того, что findможно сделать в одиночку), это не будет работать должным образом с именами файлов со встроенными пробелами и потенциально удалит неправильные файлы.
mklement0
Команда, которая хранит «подлежащие сохранению» файлы в другом месте ( /tmp_backup), плохо работает, если она прервана - с точки зрения пользователя все файлы исчезли, если они не знают, куда их искать, чтобы вернуть их обратно , По этой причине я не одобряю такой тип стратегии.
Крейг МакКуин
20
Предполагая, что файлы с этими именами существуют в нескольких местах в дереве каталогов, и вы хотите сохранить их все:
find .-type f !-regex ".*/\(textfile.txt\|backup.tar.gz\|script.php\|database.sql\|info.txt\)"-delete
Приостановлено до дальнейшего уведомления. источник
19
Вы можете использовать переменную окружения GLOBIGNORE в Bash.
Предположим, что вы хотите удалить все файлы, кроме php и sql, тогда вы можете сделать следующее:
Установка GLOBIGNORE таким образом игнорирует php и sql из подстановочных знаков, используемых как "ls *" или "rm *". Таким образом, использование «rm *» после установки переменной удалит только файлы txt и tar.gz.
Это сложнее, потому что вы должны позаботиться о разрешениях после того, как скопируете их обратно.
Ромул
2
@RemusAvram Вы можете использовать соответствующие ключи с cpили rsyncдля сохранения разрешений. В любом случае, это просто альтернативный метод (приведенный в качестве предложения), который имеет здесь свое место в качестве ответа на ФП.
gniourf_gniourf
Это может не подходить во многих ситуациях, когда сохраняемые файлы активно используются другими процессами. Кроме того, громоздкие файлы, которые нужно удалить, являются лишь небольшим подмножеством, и в нем задействовано большое количество файлов.
codeforester
@codeforester: конечно. Но бывают ситуации, когда это уместно, хотя ... на самом деле я не вижу смысла в вашем комментарии :).
gniourf_gniourf
6
Вы можете написать цикл для этого ...%)
for x in*doif["$x"!="exclude_criteria"]then
rm -f $x;fidone;
Немного опоздал на ОП, но, надеюсь, полезен для тех, кто попал сюда намного позже от Google ...
Я нашел ответ @awi и комментарий -delete @Jamie Bullock действительно полезным. Простая утилита, позволяющая делать это в разных каталогах, игнорируя каждый раз разные имена / типы файлов с минимальным набором текста:
НЕ работает для файлов. rm !(myfile.txt)удаляет все в том числеmyfile.txt
хаверим
должен выполнить shopt -s extglobсначала, как указал @ pl1nk
zhuguowei
Да, это очень важно , чтобы активировать расширенную подстановку ( extglob ) в Баше, я делаю это в ежедневной рутинной основе, в течение нескольких Маков в лабораториях: shopt -s extglobа затем cd /Users/alumno/и , наконец rm -rf !(Applications|Virtualbox*VMs|Downloads|Documents|Desktop|Public|Library) Читайте о продлено глобировании здесь
juanfal
4
Просто:
rm $(ls -I "*.txt")#Deletes file type except *.txt
После этого переберите все файлы в каталоге, который вы хотите исключить, проверяя, находится ли имя файла в массиве, который вы не хотите исключать; если нет, то удалите файл.
for file in*;doif[[!" ${files[@]} "~="$file"]];then
rm "$file"fidone
Сравнение регулярных выражений неверно - оно сохранит любой файл, имя которого является подстрокой одного из защищенных файлов (хотя окружающие пробелы несколько смягчают это; но имена файлов могут содержать пробелы). Вы должны собрать массив всех файлов, затем вычесть файлы, которые вы хотите исключить из этого массива, затем удалите оставшиеся файлы.
tripleee
-1
Поскольку никто еще не упомянул об этом, в одном конкретном случае:
OLD_FILES=`echo *`... create new files ...
rm -r $OLD_FILES
(или просто rm $OLD_FILES)
или
OLD_FILES=`ls *`... create new files ...
rm -r $OLD_FILES
Возможно, вам придется использовать, shopt -s nullglobесли некоторые файлы могут быть там или не там:
Существующий ответ Леонардо Эрмосо делает это с меньшим количеством ошибок. Это не удастся для имен файлов с пробелами; использование массива элегантно решает эту конкретную проблему (а также менее решительно избегает использования заглавных букв для своих личных переменных, чего обычно следует избегать).
tripleee
-3
Вместо прямой команды, пожалуйста, переместите необходимые файлы во временный каталог за пределы текущего каталога. Затем удалите все файлы, используя rm *или rm -r *.
Затем переместите необходимые файлы в текущий каталог.
Это может не подходить во многих ситуациях, когда сохраняемые файлы активно используются другими процессами. Кроме того, громоздкие файлы, которые нужно удалить, являются лишь небольшим подмножеством, и в нем задействовано большое количество файлов.
codeforester
-3
Удалить все, кроме файла. Name:
ls -d /path/to/your/files/*|grep -v file.name|xargs rm -rf
Это приведет к ужасной ошибке и может привести к потере данных, если в вашем каталоге / файлах есть пробелы или необычные символы. Вы никогда не должны анализировать ls. mywiki.wooledge.org/ParsingLs
rm -r
подразумевается - удаляйте все остальное, включая подкаталоги, - даже если они содержат файлы с указанными именами; ИЛИ: (b) пройти по всему поддереву целевого каталога и в каждом каталоге удалить все файлы, кроме файлов с именами в списке.Ответы:
Если вы не укажете,
-type f
find также выведет список каталогов, которые вам могут не понадобиться.Или более общее решение с использованием очень полезной комбинации
find | xargs
:например, удалить все не TXT-файлы в текущем каталоге:
print0
И-0
комбинация необходима , если есть пробелы в любом из имен файлов , которые должны быть удалены.источник
find . -type f -not -name '*ignore1' -not -name '*ignore2' | xargs rm
-print0 | xargs -0 rm --
тебя можно просто-delete
Extglob (Extended Pattern Matching) должен быть включен в BASH (если он не включен):
источник
shopt -s extglob; rm -rf !(README|LICENSE)
. Есть идеи почему?"find
с-delete
опцией.bash
было использовано, напримерdash
, гдеextglob
не поддерживается. Однако в интерактивнойbash
оболочке команда также не будет работать, как указано, хотя и по другим причинам. Суть в том, чтобы выполнить себяshopt -s extglob
; РАЗ УСПЕШНО ВКЛЮЧЕНО (проверьте с помощьюshopt extglob
), выполнитеrm -rf !(README|LICENSE)
. (Хотяextglob
он еще не включен,!(...)
оценивается расширением истории ДО того, как команды будут выполнены; поскольку это, скорее всего, не сработает, команда NEITHER будет выполнена иextglob
никогда не будетshopt -s extglob
перспективе в интерфейсе командной строки, я должен был повторно его в свой файл сценария Это решило проблему для меня..find . | grep -v "excluded files criteria" | xargs rm
При этом будут перечислены все файлы в текущем каталоге, затем перечислены все те, которые не соответствуют вашим критериям (остерегайтесь совпадения с именами каталогов), а затем удалите их.
Обновление : на основе ваших правок, если вы действительно хотите удалить все из текущего каталога, кроме файлов, которые вы перечислили, это можно использовать:
Это создаст резервную копию каталога
/tmp_backup
(у вас есть права root, верно?), Переместит файлы, которые вы перечислили в этот каталог, рекурсивно удалите все в текущем каталоге (вы знаете, что вы находитесь в правильном каталоге, не так ли?), Переместите вернуться к текущему каталогу все/tmp_backup
и, наконец, удалить/tmp_backup
.Я выбираю каталог резервного копирования в качестве корневого, потому что если вы пытаетесь рекурсивно удалить все из корневого каталога, у вашей системы будут большие проблемы.
Конечно, есть более элегантные способы сделать это, но этот довольно простой.
источник
find . | egrep -v "\.tex|\.bib" | xargs rm
find . -maxdepth 1 | grep -v "exclude these" | xargs rm -r
работает намного быстрее, так как не нужно детализировать каталоги без необходимости.find
конвейер: проблемы эффективности в стороне (3 команды используются для того, чтоfind
можно сделать в одиночку), это не будет работать должным образом с именами файлов со встроенными пробелами и потенциально удалит неправильные файлы./tmp_backup
), плохо работает, если она прервана - с точки зрения пользователя все файлы исчезли, если они не знают, куда их искать, чтобы вернуть их обратно , По этой причине я не одобряю такой тип стратегии.Предполагая, что файлы с этими именами существуют в нескольких местах в дереве каталогов, и вы хотите сохранить их все:
источник
Вы можете использовать переменную окружения GLOBIGNORE в Bash.
Предположим, что вы хотите удалить все файлы, кроме php и sql, тогда вы можете сделать следующее:
Установка GLOBIGNORE таким образом игнорирует php и sql из подстановочных знаков, используемых как "ls *" или "rm *". Таким образом, использование «rm *» после установки переменной удалит только файлы txt и tar.gz.
источник
GLOBIGNORE
переменной является использование подоболочки:(GLOBIGNORE='*.php:*.sql'; rm *)
Я предпочитаю использовать список подзапросов:
источник
Так как никто не упомянул это:
источник
cp
илиrsync
для сохранения разрешений. В любом случае, это просто альтернативный метод (приведенный в качестве предложения), который имеет здесь свое место в качестве ответа на ФП.:)
.Вы можете написать цикл для этого ...%)
источник
Немного опоздал на ОП, но, надеюсь, полезен для тех, кто попал сюда намного позже от Google ...
Я нашел ответ @awi и комментарий -delete @Jamie Bullock действительно полезным. Простая утилита, позволяющая делать это в разных каталогах, игнорируя каждый раз разные имена / типы файлов с минимальным набором текста:
rm_except (или как вы хотите это назвать)
например, удалить все, кроме текстовых файлов и foo.bar:
Похоже на @mishunika, но без условия if.
источник
Если вы используете,
zsh
который я очень рекомендую.С участием
extended_glob
источник
Попытка это работало с:
но имена с пробелами (как всегда) жесткие. Пробовал также с
Virtualbox\ VMs
кавычками. Он всегда удаляет этот каталог (Virtualbox VMs
).источник
rm !(myfile.txt)
удаляет все в том числеmyfile.txt
shopt -s extglob
сначала, как указал @ pl1nkshopt -s extglob
а затемcd /Users/alumno/
и , наконецrm -rf !(Applications|Virtualbox*VMs|Downloads|Documents|Desktop|Public|Library)
Читайте о продлено глобировании здесьПросто:
Или:
источник
ls
вывода может стать проблемой. Смотрите здесь для подробной информации.Сделайте файлы неизменяемыми. Даже root не сможет удалить их.
Все остальные файлы были удалены.
В конце концов вы можете сбросить их изменяемыми.
источник
Это похоже на комментарий от @ siwei-shen, но вам нужен
-o
флаг, чтобы сделать несколько шаблонов.-o
Флаг стоит за «или»find . -type f -not -name '*ignore1' -o -not -name '*ignore2' | xargs rm
источник
Вы можете сделать это с двумя последовательностями команд. Сначала определите массив с именами файлов, которые вы не хотите исключать:
После этого переберите все файлы в каталоге, который вы хотите исключить, проверяя, находится ли имя файла в массиве, который вы не хотите исключать; если нет, то удалите файл.
источник
Поскольку никто еще не упомянул об этом, в одном конкретном случае:
(или просто
rm $OLD_FILES
)или
Возможно, вам придется использовать,
shopt -s nullglob
если некоторые файлы могут быть там или не там:без нульглоба,
echo *.sh *.bash
может дать вам «a.sh b.sh * .bash».(Сказав все это, я сам предпочитаю этот ответ , хотя он не работает в OSX)
источник
Вместо прямой команды, пожалуйста, переместите необходимые файлы во временный каталог за пределы текущего каталога. Затем удалите все файлы, используя
rm *
илиrm -r *
.Затем переместите необходимые файлы в текущий каталог.
источник
Удалить все, кроме файла. Name:
источник