Как удалить все файлы в папке, кроме некоторых указанных файлов?

11

Я хочу удалить все файлы в каталоге, оставив только некоторые указанные файлы, они не имеют ничего общего по имени. Как я мог этого достичь?

Например, имена файлов, которые я хочу сохранить:

file_1.png, another_file.jpg,some_music.mp3

AGamePlayer
источник

Ответы:

14

Если вы используете Bash:

shopt -s extglob
rm -- !(file1|file2|file3)

Первая строка просто активирует расширенное сопоставление с образцом, и после этого мы используем один из них:

!(pattern-list) соответствует чему-либо, кроме одного из данных шаблонов

и список шаблонов представляет собой список из одного или нескольких шаблонов, разделенных символом |.


Или с zsh

setopt extendedglob
rm -- ^(file1|file2)

Или, более портативный, используя find:

find . -maxdepth 1 ! -name 'file1' ! -name 'file2' -type f -exec rm -v {} +
jimmij
источник
3
Может быть полезно включить как вернуть необязательное поведение оболочки back ( shopt -u extglob).
geedoubleya
7

Создайте подкаталог tmp, переместите все файлы, которые вы хотите сохранить, в этот каталог и сделайте rm -f *потом. Это не повлияет на tmpкаталог.

После этого просто сделайте:

mv tmp/* .
rmdir tmp

(Предполагается, что ни один из перемещенных файлов не начинается с точки).

Это один из немногих случаев, когда имеет смысл использовать мышь и файловый браузер, такой как Nautilus, где вы можете Ctrlщелкнуть несколько файлов, которые хотите сохранить, и затем использовать меню: Edit -> Invert Selectionполучить другие файлы и затем удалить их. ,

Энтон
источник
перемещение файлов в каталог tmp звучит хорошо. Во всяком случае, я должен сделать это с помощью командной строки. Благодарность!
AGamePlayer
3
@AwQiruiGuo Преимущество tmp заключается в том, что он сначала разделяет файлы на два набора, а затем безвозвратно удаляет те, которые вам не нужны. Таким образом, вы можете запустить, lsчтобы увидеть, не пропустили ли вы какие-либо файлы, которые хотите сохранить.
Энтон
2

Добавьте имена файлов, которые вы хотите сохранить, в текстовый файл, по одному в строке. Этот файл не должен быть в каталоге, или вы должны добавить его имя тоже.

Если имя вашего каталога foo, а имя файла - bar , сделайте следующее.

find foo -type f -print0|grep -vzZ -f bar|xargs -0 rm

Это делает следующее:

  1. find -type fищет имена всех файлов в foo и его подкаталогах и печатает их в STDOUT. С опцией -print0он разделяет имена файлов с байтами NUL.
  2. grep -v -f barисключает все имена файлов, которые соответствуют строке в строке . С опцией -zон обрабатывает свои входные данные как набор строк, разделенных байтом NUL, с опцией -Zон ограничивает свой вывод байтом NUL.
  3. xargs rmзвонит rmнесколько раз, чтобы удалить файлы. С параметром -0он обрабатывает свой ввод как набор строк, разделенных байтом NUL.

Это работает с именами файлов, содержащими пробелы.

Матиас Вайднер
источник
Это не сработает, поскольку в именах файлов могут быть символы новой строки.
Энтон
@Anthon изменил параметры find, grep, xargs, чтобы справиться с именами файлов, содержащими пробелы, включая символ новой строки
Mathias Weidner
Если вы хотите использовать, findя бы предпочелfind . -maxdepth 1 ! -name 'file1' ! -name 'file2' -type f -exec rm -vi {} +
Jimmij