Удаление всех файлов в папке, кроме файлов X, Y и Z

17

У меня есть много файлов и папок в определенной папке, и я хочу удалить их все; однако я хотел сохранить файлы X, Y и Z.

Есть ли способ, которым я могу сделать что-то вроде: rm * | but NOT grep | X or Y or Z

Amit
источник
Я предполагаю, что я могу использовать какое-то регулярное выражение там, которое будет делать это?
Амит

Ответы:

16

Вместо использования rm может быть проще использовать find . Такая команда удалит все, кроме файла с именем «file»

find . \! -name 'file' -delete

Многие версии должны поддерживать глобализацию и сопоставление регулярных выражений.

Вы также можете передать вывод команды find в rm

find . \! -name '*pattern*' -print0 | xargs --null rm 
Zoredache
источник
3
И это позволяет вам точно определить, какие файлы будут удалены при удалении, -deleteа также какие файлы будут сохранены при удалении -deleteи \!.
Шон Дж. Гофф
1
осторожен, findрекурсивен! так что все подкаталоги файлов, не соответствующие ' pattern ', также будут удалены
Александр Холден Дейли
Путь через xargs требует -depth, чтобы предотвратить попытку удаления каталогов перед включенными в них файлами. Однако я думаю, что rm также не удалит каталоги.
неизвестный пользователь
9

Использование zsh, с setopt EXTENDED_GLOBиспользованием ~оператора ( кроме )

rm -- *~(x|y|z)

или ^оператор (отрицание):

rm -- ^(x|y|z)

Но вы, вероятно, должны вместо этого переместить файлы в другое место, а затем удалить все. Это намного безопаснее с точки зрения проскальзывания пальцев, например, попадания слишком рано.

wnoise
источник
5

Более поздние версии bash имеют extglobопцию оболочки, которая дает вам синтаксис для выполнения того, что вы хотите (проверьте вашу справочную страницу в разделе «Расширение пути», чтобы увидеть, есть ли в вашей установленной версии):

$ shopt -s extglob  # turn on extended globbing
$ rm !(X|Y|Z)

Чтобы проверить, я предлагаю вам сначала заменить rmна, echoчтобы увидеть, является ли список файлов, которые будут удалены, то, что вы ожидаете.

CAMH
источник
5
ls -1 | grep -v "^[XYZ]$" # | xargs rm -r

Внимание: запустите команду и, если файлы, которые нужно удалить, являются правильными, запустите ее снова и удалите хеш-символ "#".

Если имена файлов более сложны,

ls -1 | egrep -v "^file1$|^filename2$|^f1le$" # | xargs rm -r

Опять же, сначала посмотрите на результаты, затем удалите знак хеша.

Эта версия, как предлагается в комментариях, сохраняет некоторые символы и выглядит немного яснее.

ls -1 | egrep -v "^(file1|filename2|f1le)$" # | xargs rm -r
ddeimeke
источник
Предложенное редактирование ddeimeke состоит в том, чтобы изменить egrepаргумент на"^(file1|filename2|f1le)$"
Michael Mrozek
Если у вас есть три файла a, bи a bпервая программа будет удалить - если вы поставите аЬ в Grep часть: "^[ab]$" aи , bно не a bпросто в отличие от ваших намерений. Вторая команда сделает то же самое. И третий тоже. Вы не должны использовать 'ls' в скриптах, за очень, очень редкими исключениями. Просто не делай этого.
пользователь неизвестен
3

Переместите файлы, которые вы хотите сохранить. Поднимитесь на один уровень выше, удалите папку. Пересоздайте папку и переместите эти файлы обратно.

Алекс
источник
Интересно, почему минус? .. На самом деле это и проще, и безопаснее, чем что-либо, предложенное другими: вы просто не можете выстрелить себе в ногу, нажав какой-то специальный символ в имени файла.
Алекс
a) Вы перемещаете свой файл X на один каталог вверх, где существует файл X - безмолвно удален, пропал. б) Вы в топ-директоре, где не существует «вверх». в) Вы находитесь в своем доме, и у вас нет разрешения на запись в / home. Если вы вложили свой совет в сценарий, без проблем протестировали его и использовали в такой ситуации - Пэн!
пользователь неизвестен
2
а) Эй, я сказал «переместить файлы на один уровень выше»? Я сказал, убери их. б) Итак, вы пытаетесь удалить все файлы /, а? Не очень практично. в) Попытка удалить все файлы в вашем $HOMEтоже не очень практична.
Алекс
Ты прав, прости.
пользователь неизвестен
0

Это то, что я настроил как сценарий .sh для выхода из OSX / MacOS, работает достаточно хорошо.

#! /bin/bash
for dir in /PathToFolder/*
 do
    if [ ! "$dir" = "/PathToFolder/FolderToKeep1" ] && [ ! "$dir" = "/PathToFolder/FolderToKeep2" ] && [ ! "$dir" = "/PathToFolder/FolderToKeep3" ] && [ ! "$dir" = "/PathToFolder/FolderToKeep4" ] && [ ! "$dir" = "/PathToFolder/FolderToKeep5" ] && [ ! "$dir" = "/PathToFolder/FolderToKeep6" ] ; then 
      echo ${dir}
      sudo rm -R $dir user
      dscl . -delete $dir
    fi 
  done

exit 0
ICMP
источник
0

С GNU-find вы можете использовать ключ -delete, который удаляет каталоги, если они тоже пусты:

 find tmp -not -name X -not -name Y -not -name Z -delete 
Пользователь неизвестен
источник
Если X, Y или Z является каталогом, это также приведет к удалению файлов внутри них. find tmp -maxdepth 1 -not -name X -not -name Y -not -name Z -deleteэто один из способов обойти это.
Жиль "ТАК - перестань быть злым"
Так как папки в Unix - это файлы (все, что является файлом), возможно, это то, что предназначено. Вопрос прямо говорит: «У меня есть много файлов и папок в определенной папке, и я хочу удалить их все;» - и если вы хотите исключить Y, возможно, вы знаете, является ли Y каталогом или нет.
пользователь неизвестен
Это также приведет к удалению, tmpесли в нем не было файлов X/ Y/ Z. Примечание !в качестве стандартного эквивалента GNU -not( -deleteтакже является расширением GNU)
Стефан
@ StéphaneChazelas: Из вопроса, удаление папок (все из них) это то, что просили. Поскольку удар требует маскировки, я предпочитаю печатать -не. Может зависеть от немецкой раскладки клавиатуры, где Backslash требуется Alt-Gr.
пользователь неизвестен