Видалення всіх файлів у папці, крім файлів X, Y та Z


17

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

Чи є спосіб я зробити щось на кшталт: rm * | but NOT grep | X or Y or Z


Я припускаю, що я можу використовувати там якийсь регулярний вираз, який зробить це?
Аміт

Відповіді:


16

Замість того щоб використовувати гт, може бути простіше використовувати знахідку . Така команда видалить усе, крім файлу, названого саме "файл"

find . \! -name 'file' -delete

Багато версій файлів повинні підтримувати глобальну та регулярну відповідність виразів.

Ви також можете передати висновок знаходження в rm

find . \! -name '*pattern*' -print0 | xargs --null rm 

3
І це дозволяє точно бачити, які файли будуть видалені шляхом видалення -delete, а також які файли будуть збережені шляхом видалення -deleteта \!.
Шон Дж. Гофф

1
обережно, findрекурсивно! тому всі підкаталоги файлів, що не відповідають " шаблону ", також будуть видалені
Олександр Холден Далі,

Шлях через xargs потребує -depth, щоб запобігти спробі видалення каталогів перед файлами, що входять до них. Однак я думаю, що rm також не видалить каталоги.
користувач невідомий

9

Використання zsh, with setopt EXTENDED_GLOB, використання ~оператора ( крім )

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

або ^оператор (заперечення):

rm -- ^(x|y|z)

Але, ймовірно, слід замість цього перемістити файли в інше місце, а потім видалити все. Це набагато безпечніше з точки зору ковзання пальців, наприклад, натискання клавіш занадто рано.


5

Пізніші версії bash мають extglobопцію оболонки, яка дає вам синтаксис для того, щоб робити те, що ви хочете (перегляньте свою сторінку man у розділі "Розширення імені Pathname", щоб побачити, чи є у вашій встановленій версії):

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

Для тестування, я пропоную вам спочатку замінити rmз , echoщоб побачити , якщо список файлів , які будуть видалені , це те , що ви очікуєте.


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 редакція - це змінити egrepаргумент на"^(file1|filename2|f1le)$"
Michael Mrozek

Якщо у вас є три файли a, bі a bперша програма буде видалена - якщо ви введете ab в grep-частину: "^[ab]$" aта bні a b, просто проти ваших намірів. Друга команда зробить те саме. І третя теж. Не слід використовувати 'ls' у скриптах, за дуже-дуже рідкісними винятками. Просто не роби цього.
користувач невідомий

3

Перемістіть файли, які ви хочете зберегти. Перейдіть на один рівень, видаліть папку. Відновіть папку та перемістіть ці файли назад.


Цікаво, чому мінус? .. Насправді це і простіше, і безпечніше, ніж все, що пропонують інші: ви просто не можете застрелити себе в ногу, натиснувши якусь спеціальну табличку у назві файлу.
алекс

а) Ви переміщуєте свій файл X на один каталог вгору, де існує файл X - мовчки видаляється, йде. b) Ви знаходитесь у першому режимі, де немає "вгору". в) Ви знаходитесь у своєму домі і не маєте дозволу писати в / додому. Якщо ви ввели свою пораду в сценарій і протестували її без проблем і використовуєте її в такій ситуації - пенг!
користувач невідомий

2
а) Гей, я сказав: "перемістити файли на один рівень"? Я вже казав, відсуньте їх. b) Отже, ви намагаєтесь видалити всі файли /, так? Не дуже практично. c) Спроба видалити всі файли з вашого $HOMEтакож не є практичною.
alex

Ти маєш рацію, пробач.
користувач невідомий

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

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éphane Chazelas

@ StéphaneChazelas: З питання запитання про видалення папок (усіх). Оскільки чубок потребує маскування, я вважаю за краще вводити -не. Можливо, це залежить від німецької розкладки клавіатури, де Backslash потрібен Alt-Gr.
користувач невідомий
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.