Як видалити всі файли в каталозі, крім деяких?


123

Мені потрібно видалити всі файли в каталозі, але виключити деякі з них. Наприклад, у каталозі з файлами a b c ... zмені потрібно видалити всі, крім uі p. Чи є простий спосіб це зробити?


Наведені нижче відповіді набагато кращі, але ви можете просто змусити файли зберегти лише для читання, видалити всі, а потім змінити їх до початкових дозволів (доки ви не використовуєте rm -f). Ви повинні знати, які дозволи відновити, і ви повинні знати, що нічого не потрібно писати до них під час процесу доступу. Ось чому інші відповіді кращі.
Джо

1
Якщо ви також хочете видалити приховані файли, запустіть shopt -s dotglobперед запуском rm (...).

Відповіді:


108

Що я роблю в цих випадках - це набрати

rm *

Потім натискаю Ctrl+ X, *щоб розгорнути * всі видимі імена файлів.

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


25
Я думаю, це працює лише до тих пір, поки список файлів, який також *розширюється, не стає занадто довгим. : -}
Фріріх Раабе

9
Esc з наступним * також розширить "*".
повільний отрут

2
@SantoshKumar: Це не має для мене сенсу. Розширення завжди працюватиме, це не залежить від того, яку команду ви хочете використовувати згодом.
Der Hochstapler

2
@OliverSalzburg Вибачте, поєднання трохи заплутане. Я думаю, вам слід писати як Ctrl+ Shift+ x+*
Сантош Кумар

2
@SantoshKumar: Але це не поєднання.
Der Hochstapler

143

Для rmвсіх, крім u,pbash, просто введіть:

rm !(u|p)

Для цього потрібно встановити наступний варіант:

shopt -s extglob

Дивіться більше: глобус - Вікі Грега


1
у вас повинно бути активне "extglobbing": shopt -s extglob
sparkie

18
Вам потрібно shopt -s extglob, @Ashot. Крім того, це просто файли, а не каталоги, саме тому я видалив -rfпараметри у вашій команді.
slhck

3
Якщо необхідно виключити один файл з вибору файлів, спробуйте наступне: rm !(index).html. Це видалить усі файли, що закінчуються на ".html", за винятком "index.html".
mzuther

71

Можна використовувати find

find . ! -name u ! -name p -maxdepth 1 -type f -delete
  • ! заперечує наступний вираз
  • -name вказує ім'я файлу
  • -maxdepth 1зробить процес пошуку лише вказаним каталогом ( findза замовчуванням проходить каталоги)
  • -type f буде обробляти лише файли (а не, наприклад, каталоги)
  • -delete видалить файли

Потім ви можете налаштувати умови, переглядаючи сторінку пошуку чоловіка

Оновлення

  • Майте на увазі, що порядок елементів виразів є значним (див. Документацію)
  • Спробуйте спочатку свою команду, використовуючи -printзамість-delete

    find . ! -name u ! -name p -maxdepth 1 -type f -print

5
Порядок предикатів тут критичний. Якщо поставити їх -deleteвідразу після .катастрофи (видалить усі файли в CWD)
Michał Šrajer

Це можна було б записати більш компактно якfind . -maxdepth 1 -type f -name '[^up]' -delete
kojiro

4
@kojiro так, але лише для файлів, які містять лише одну букву. З більш складними назвами регекс може бути безладом.
Маттео

2
findє моїм найкращим другом, особливо, коли глобусів занадто багато
Теренс Джонсон

43

Простий:

mvпотрібні файли у верхньому каталозі, rmв каталозі, а потім mvназад.


13
Offcourse, mv їх до каталогу вище. Намагайтеся не додавати їх до підкаталогу, який ви видаляєте ...
Konerak

@Konerak: rmбез -rвидалення підкаталогів.
reinierpost

11
Це дозволить перезаписати файли з тим самим іменем у каталозі призначення
Маттео,

7
Я це заперечую, тому що, хоча це може бути зручно, він також не є атомним і ефективно видаляє всі файли з каталогу за короткий проміжок часу; це було б неприйнятно, якщо, наприклад, файли діляться в мережі.
sam hocevar

15

Дещо схожий на цю відповідь, але жодних спеціальних параметрів не потрібно, наскільки я знаю, наступним є "старовинна" функціональність, підтримувана будь-якою (смутно) / bin / sh, що нагадує оболонку (наприклад, bash, zsh, ksh тощо)

rm [^up]

2
Це працює для 1-іменних імен файлів. Що стосується довших імен, відповідь спаркі краще.
glenn jackman

3
Що було б не так rm [^up]*? Я подібні речі роблю досить часто.
CVn

3
@ MichaelKjörling - це видалить усі файли, що починаються з u чи p, не лише ті, що мають імена u та p. Я думаю, що ОП (@Ashot) означало az і u, p тощо. символічно, а не буквально.
Sudipta Chatterjee

4
@HobbesofCalvin Це видалило б усі файли, що не починаються з u чи p, а не ті, що починаються з них.
rjmunro

@rjmunro - дякую, пропустив це! :)
Sudipta Chatterjee

11

Робити це без пошуку:

ls | grep -v '(u|p)' | xargs rm

(Редагувати: "u" та "v", як і в інших місцях тут, використовуються як загальні версії цілих регулярних виразів.

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


grep не буде обробляти розширений regexpt за замовчуванням: або використовувати -Eабоegrep
Matteo

2
це виключає будь-який файл, що містить a uабо ap
Маттео

@Matteo Ні, це не буде. Grep не є копіюванням файлів, а виведенням команди ls. Ви думаєте про щось на зразок, grep -L (u|p)' * | xargs rmде -Lзначить перелічити назви файлів, які не містять відповідності.
rjmunro

4
О, ви маєте на увазі будь-який файл, чиє ім’я містить, uабо pне будь-який файл, що містить a uчи a p. Це правильно. Ви можете виправити, скориставшисьegrep -v '^(u|p)$'
rjmunro

1
Ось видаліть усе, крім цих сірників! ls | grep -v 'vuze\|progs' | xargs rm -rf
Нік

6

В zsh:

setopt extended_glob  # probably in your .zshrc

тоді

rm ^(u|p)

або

rm *~(u|p)

Другий буде працювати , навіть якщо у вас є ^в $histcharsпротягом підміни історії, і, звичайно , ви можете поставити довільну Glob перед ~.


5

GLOBIGNORE займає список, розділений двокрапкою

GLOBIGNORE=u:p
rm *

12
Це не працює на моїй оболонці (GNU bash 4.1.5 (1)). Обов’язково спершу тестуйте його на щось трохи менш шкідливе, ніжrm або в тестовому каталозі!
CVn

3

Ще в епоху дискети у мене був виконаний dos під назвою "За винятком", який тимчасово переміщав би речі з поточного каталогу та виконував команду, так що ви можете сказати:

крім * .txt del *. *

щоб видалити все, крім ваших текстових файлів.

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


2
Це нагадало мені те саме. Але тимчасове переміщення з папки може бути не гарною ідеєю в епоху багатозадачності :)
Седат Капаноглу

3
 find . -maxdepth 1 ! -name "u" ! -name "p" -type f -exec rm -rf {} \;

Це видалить усі файли, крім u і p в unix


2

Для тих, хто вважає за краще вказувати довільні складні виключення шаблонів (що охоплюють усі постраждалі назви файлів) у повному стилі egecs regexp, posix-awk або розширений posix (див. Сторінку пошуку man), я б рекомендував цей. Це виключає uі pв поточному режимі в цьому прикладі. Це може бути зручно для сценаріїв.

find -regextype posix-awk ! -regex './(u|p)' -print0 | xargs -0 rm -rf

Вам потрібно вказати каталог перед виразом (`find. -Regextype ...).
Маттео

-regextypeпрацюватиме лише над версіями GNU
Маттео

ні - моя версія пошуку (видалення debian) остаточно не вимагає явного каталогу перед виразом, якщо слід використовувати поточний каталог
sparkie

@sparke: це просто працює над реалізацією GNU
Маттео

@sparkie: не визначення каталогу (першого параметра) для find- це розширення findкоманди GNU . Те саме стосується -regextypeопціону. Крім того, ваша команда також видалить файли в підкаталогах, тоді як в оригінальному питанні чітко задавались файли в каталозі.
Мікко Ранталайнен

1

Я завжди використовую:

rm [a-o,q-t,v-z]*

Це дозволить вам визначити, наскільки зернисте ви хочете це зробити. Отже, якщо ви хочете видалити файли через o і Z, ви можете використовувати:

rm [a-o,z]*

1

Ще одна версія, що використовує xargs:

ls -1 | grep -v do_not_delete | xargs -I files rm "files"

Зверніть увагу, що xargs -Iпотрібно для правильної обробки імен файлів, включаючи пробіли.


1

Ще один:

for FILE in ./*; do if [[ $FILE != ./u* ]] || [[ $FILE != ./p* ]];then rm $FILE; fi; done;

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

І це чисто баш добро.


1

Ось ще один варіант. Ви можете ввести:

rm -i *

або:

rm --interactive *

Тож rmпопросимо підтвердити видалення кожного файлу.


1

Використання:

find . -type f ! -name 'u' ! -name 'p' ! -name '*.ext' -delete
find . -type d ! -name 'u' ! -name 'p' ! -name '*.ext' -delete

щоб видалити всі файли, включаючи каталоги, крім файлів u, p та .ext.


0

Простий спосіб, який важко зіпсувати: скажімо, ви хочете видалити все, крім * .pdf:

mkdir tmp
mv *.pdf tmp
rm *
mv tmp/* .
rm -r tmp
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.