Как исключить некоторые файлы из механизма расширения имени файла в bash?

14

У меня есть каталоги файловой системы Ubuntu в корневом каталоге, и я случайно скопировал сотни файлов в корневой каталог.

Я интуитивно пытался удалить скопированные файлы, исключив файловую систему, как

rm -rf !{bin,sbin,usr,opt,lib,var,etc,srv,libx32,lib64,run,boot,proc,sys,dev} ./.

но это не работает. Как правильно исключить некоторые каталоги при удалении целого?

РЕДАКТИРОВАТЬ: Никогда не пытайтесь использовать команды здесь, не зная, что делать!

кенна
источник
1
Какую оболочку вы используете? Глобализация имени файла зависит от оболочки, когда дело доходит до таких причудливых вещей.
Кусалананда
2
Не ответ, но я бы использовал, например mc. Выберите все с помощью *, затем отмените выбор определенных файлов с помощью -или Insert.
PBM
1
Можете ли вы объяснить, что такое mc?
MikeP
@Kusalananda это/bin/bash
кенна
3
@MikeP: mcMidnight Commander, очень полезная имитация Norton Commander. Он работает в терминале. (И Midnight Commander, и Norton Commander являются примерами так называемого православного файлового менеджера .)
AlexP

Ответы:

21

Поскольку вы используете bash:

shopt -s extglob
echo rm -rf ./!(bin|sbin|usr|...)

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

Примечание. Приведенная выше команда не удаляет скрытые файлы (имена которых начинаются с точки). Если вы хотите удалить их, активируйте также dotglobопцию:

shopt -s dotglob
jimmij
источник
Я использовал его, чтобы успешно очистить файловую систему. Сначала я проверил это в каталоге. Я также пробовал rm -rf ./!(bin,sbin,..)разделить запятыми, но он удаляет все каталоги.
KENN
Что это за !(...)синтаксис? Из примера, который я интуитивно думал, ls ./!(*/)будут перечислены только файлы, но это не сработает.
giusti
@giusti Этот синтаксис представляет собой расширенное сопоставление с образцом в механизме расширения имени файла - его описание вы найдете в руководстве по bash в главе «Расширение пути». Его нельзя использовать для исключения типов файлов, только имен, как со звездочкой *или другими глобусами.
Джимми
12

Эта команда покажет все не-каталоги в /:

find / -maxdepth 1 -type f

После того, как вы абсолютно уверены, что нет файлов, которые вы хотите сохранить, вы можете использовать:

find / -maxdepth 1 -type f -delete

Безопаснее было бы переместить их в другое место, чтобы убедиться, что вы не удаляете то, что хотите сохранить:

mkdir /root/preserve
find / -maxdepth 1 -type f -exec mv -- "{}" /root/preserve/\;

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

Если это невозможно, что-то вроде этого может помочь:

#!/bin/bash
declare -a excludes
for item in root sys 'lost+found' mnt home proc etc opt boot lib lib64 libx32 sbin media srv dev var usr bin tmp run; do
    excludes+=("$item")
done
if ! [[ -d /root/preserve ]]; then
    mkdir -p /root/preserve
fi
IFS="\n"
for item in find / -type d -maxdepth 1; do
    really=true
    for exclude in ${excludes[@]}; do
        if [[ "$exclude" == "${item#/}" ]]; then
            really=false
        fi
    done
    if [[ "true" == "$really" ]]; then
        mv -- "$item" /root/preserve/
    fi
done

После того, как вы прошли тест на крик (то есть ваша система все еще работает, и вы не кричите от боли), вы можете удалить содержимое /root/preserve/ .

Важное примечание: что бы вы ни делали, даже не думайте о запуске какой-либо перестановки rm -fr [ANYTHING GOES HERE] /.

DopeGhoti
источник
Ваше решение удаляет только файлы, но вокруг также есть папки.
KENN
1
Слишком много раз я слышал вопли ужаса от плохо нацеленного rm. Как скрипт rm -fr $somepath/с somepathнеинициализированным в нем. Я мог бы пойти дальше, выражая, насколько это серьезно, но решил остаться дружелюбным по отношению к семье в своем наставлении.
DopeGhoti
3

Это должно выполнить работу (хотя и не так, как просит ОП):

ls -1 >1.txt
pico 1.txt 

удалите все файлы / каталоги, которые вы хотите сохранить

xargs rm < 1.txt

Если все ваши файлы имеют одинаковый формат имени, дату или что-то еще, есть другие методы.

Я бы посмотрел на иноды и посмотрел, являются ли они последовательными через ls -i | sort, и если они есть, то новые файлы будут иметь большие иноды. Затем, используя тот же тип процесса, что и выше ...

ls -iF1 | sort |cut -c10- | grep -vE "\/|\@" >i.txt   #This part removes entries that are not regular files, such as directories and links.  
pico i.txt
xargs rm < i.txt

в приведенной выше команде cut сначала проверьте свой список inode, чтобы убедиться, что это правильное количество.

MikeP
источник