Rm все файлы, кроме некоторых

При использовании sudo rm -r, как я могу удалить все файлы, за исключением следующего:

textfile.txt
backup.tar.gz
script.php
database.sql
info.txt

Ответ 1

find [path] -type f -not -name 'textfile.txt' -not -name 'backup.tar.gz' -delete

Если вы не укажете -type f find, также будут перечислены каталоги, которые вы, возможно, не захотите.


Или более общее решение, использующее очень полезную комбинацию find | xargs:

find [path] -type f -not -name 'EXPR' -print0 | xargs -0 rm --

например, удалите все не txt файлы в текущем каталоге:

find . -type f -not -name '*txt' -print0 | xargs -0 rm --

Комбинация print0 и -0 необходима, если в любом из файлов, которые должны быть удалены, есть пробелы.

Ответ 2

rm !(textfile.txt|backup.tar.gz|script.php|database.sql|info.txt)

Должна быть включена опция extglob (Extended Pattern Matching) в BASH (если она не включена):

shopt -s extglob

Ответ 3

find . | grep -v "excluded files criteria" | xargs rm

Здесь будут перечислены все файлы в текущем каталоге, а затем будут перечислены все те, которые не соответствуют вашим критериям (остерегайтесь соответствия имен каталогов), а затем удалите их.

Обновить: на основе вашего редактирования, если вы действительно хотите удалить все из текущего каталога, кроме перечисленных вами файлов, это можно использовать:

mkdir /tmp_backup && mv textfile.txt backup.tar.gz script.php database.sql info.txt /tmp_backup/ && rm -r && mv /tmp_backup/* . && rmdir /tmp_backup

Будет создан резервный каталог /tmp_backup (у вас есть права на root, правильно?), переместите файлы, которые вы указали в этот каталог, удалите рекурсивно все в текущем каталоге (вы знаете, что находитесь в правильном каталоге, вы?), вернитесь к текущему каталогу все из /tmp_backup и, наконец, удалите /tmp_backup.

Я выбираю, чтобы каталог резервного копирования был в корневом каталоге, потому что если вы пытаетесь удалить все рекурсивно из корня, ваша система будет иметь большие проблемы.

Конечно, есть более элегантные способы сделать это, но это довольно просто.

Ответ 4

Предполагая, что файлы с этими именами существуют в нескольких местах в дереве каталогов, и вы хотите сохранить их все:

find . -type f ! -regex ".*/\(textfile.txt\|backup.tar.gz\|script.php\|database.sql\|info.txt\)" -delete

Ответ 5

Вы можете использовать переменную среды GLOBIGNORE в Bash.

Предположим, вы хотите удалить все файлы, кроме php и sql, тогда вы можете сделать следующее -

export GLOBIGNORE=*.php:*.sql
rm *
export GLOBIGNORE=

Установка GLOBIGNORE, как это, игнорирует php и sql из подстановочных знаков, используемых как "ls *" или "rm *". Таким образом, с помощью "rm *" после установки переменной удаляется только файл txt и tar.gz.

Ответ 6

Так как никто не упоминал об этом:

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

Ответ 7

Немного поздно для OP, но, надеюсь, полезно для тех, кто получает здесь намного позже google...

Я нашел ответ от @awi и прокомментировал -delete by @Jamie Bullock действительно полезный. Простая утилита, поэтому вы можете сделать это в разных каталогах, игнорируя разные имена/типы файлов каждый раз при минимальном наборе текста:

rm_except (или все, что вы хотите назвать)

#!/bin/bash

ignore=""

for fignore in "[email protected]"; do
  ignore=${ignore}"-not -name ${fignore} "
done

find . -type f $ignore -delete

например. для удаления всего, кроме текстовых файлов и foo.bar:

rm_except *.txt foo.bar 

Аналогично @mishunika, но без предложения if.

Ответ 8

Вы можете написать цикл for для этого...%)

for x in *
do
        if [ "$x" != "exclude_criteria" ]
        then
                rm -f $x;
        fi
done;

Ответ 9

Попытка работать с:

rm -r !(Applications|"Virtualbox VMs"|Downloads|Documents|Desktop|Public)

но имена с пробелами (как всегда) жесткие. Пробовал также Virtualbox\ VMs вместо кавычек. Он всегда удаляет этот каталог (Virtualbox VMs).

Ответ 10

Я предпочитаю использовать список подпрограмм:

rm -r `ls | grep -v "textfile.txt\|backup.tar.gz\|script.php\|database.sql\|info.txt"`

-v, -invert-match выбирает несогласованные строки

\| Сепаратор

Ответ 11

Если вы используете zsh, который я настоятельно рекомендую.

rm -rf ^file/folder pattern to avoid

С extended_glob

setopt extended_glob
rm -- ^*.txt
rm -- ^*.(sql|txt)

Ответ 12

Просто:

rm $(ls -I "*.txt" ) #Deletes file type except *.txt

Или:

rm $(ls -I "*.txt" -I "*.pdf" ) #Deletes file types except *.txt & *.pdf

Ответ 13

Вместо того, чтобы перейти к прямой команде, переместите необходимые файлы в temp dir за пределами текущего каталога. Затем удалите все файлы с помощью rm * или rm -r *.

Затем переместите нужные файлы в текущий каталог.

Ответ 14

Это похоже на комментарий от @siwei-shen, но вам нужен флаг -o для создания нескольких шаблонов. Флаг -o означает 'или'

find . -type f -not -name '*ignore1' -o -not -name '*ignore2' | xargs rm

Ответ 15

Вы можете сделать это с помощью команды lines сначала определите массив с именем файлов, которые вы не хотите исключать

$ files=( backup.tar.gz script.php database.sql info.txt )

После этого пропустите все файлы в каталоге, который вы хотите исключить, проверяя, находится ли имя файла в массиве, который вы не хотите исключать, если он не удаляет файл.

$ for file in $(ls); do if [[ ! " ${files[@]} " ~= "$file"  ]];then rm "$file";fi;done

Вот оно!