Jak wykluczyć niektóre pliki z mechanizmu rozwijania nazw plików w bash?


14

Mam katalogi systemu plików Ubuntu w katalogu głównym i przypadkowo skopiowałem setki plików do katalogu głównego.

Intuicyjnie próbowałem usunąć skopiowane pliki, wykluczając podobny system plików

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

ale to nie działa. Jaki jest właściwy sposób wykluczenia niektórych katalogów podczas usuwania całości?

EDYCJA: Nigdy nie próbuj tutaj żadnych poleceń, nie wiedząc, co robić!


1
Jakiej powłoki używasz? Globbing nazw plików jest zależny od powłoki, jeśli chodzi o robienie takich fantazyjnych rzeczy.
Kusalananda

2
Nie odpowiedź, ale użyłbym na przykład mc. Zaznacz wszystko za pomocą *, a następnie odznacz określone pliki za pomocą -lub Insert.
pbm

1
Czy możesz wyjaśnić, co to jest „mc”?
MikeP

@Kusalananda It's/bin/bash
kenn

3
@MikeP: mcjest Midnight Commander, bardzo przydatną imitacją Norton Commander. Działa w terminalu. (Zarówno Midnight Commander, jak i Norton Commander to przykłady tak zwanego ortodoksyjnego menedżera plików .)
AlexP

Odpowiedzi:


21

Ponieważ używasz bash:

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

Polecam dodać echona początku wiersza poleceń, gdy uruchamiasz coś, co potencjalnie może wysadzić cały system. Usuń go, jeśli jesteś zadowolony z wyniku.

Uwaga: powyższe polecenie nie usuwa ukrytych plików (tych, których nazwa zaczyna się kropką). Jeśli chcesz je również usunąć, aktywuj także dotglobopcję:

shopt -s dotglob

Użyłem go do skutecznego wyczyszczenia systemu plików. Na początku testowałem to w katalogu. Próbowałem też rm -rf ./!(bin,sbin,..)oddzielić przecinek, ale usuwa wszystkie katalogi.
kyn

Jaka jest ta !(...)składnia? Z przykładu, który intuicyjnie myślałem, ls ./!(*/)że wymienię tylko pliki, ale to nie działa w ten sposób.
giusti

@giusti Ta składnia jest rozszerzonym dopasowaniem wzorca w mechanizmie rozwijania nazw plików - opis znajdziesz w podręczniku bash w rozdziale Pathname Expansion. Nie można go używać do wykluczania typów plików, tylko nazw, tak jak w przypadku gwiazd *lub innych globów.
jimmij

12

To polecenie pokaże wszystkie nie-katalogi w /:

find / -maxdepth 1 -type f

Po dokonaniu absolutnie pewien żadne pliki są tam, że chcesz zachować, można użyć:

find / -maxdepth 1 -type f -delete

Bezpieczniej byłoby przenieść je w inne miejsce, aby upewnić się, że nie usuwasz czegoś, co chcesz zachować:

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

Jeśli oprócz plików masz również katalogi dodane do katalogu głównego systemu plików, można to zautomatyzować, wykluczając katalogi LSB z automatycznego mvlub rm, ale szczerze mówiąc, ponieważ mamy do czynienia z czyszczeniem rzeczy w root systemu plików, zdecydowanie zalecam rozważenie zrobienia tego ręcznie, jeśli to w ogóle możliwe.

Jeśli nie jest to możliwe, coś takiego może załatwić sprawę:

#!/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

Po przejściu testu krzyku (tzn. System nadal działa i nie krzyczysz w udręce), możesz usunąć zawartość /root/preserve/.

Ważna uwaga: cokolwiek robisz, nawet nie myśl o uruchomieniu jakiejkolwiek permutacji rm -fr [ANYTHING GOES HERE] /.


Twoje rozwiązanie usuwa tylko pliki, ale są też foldery.
hodowla

1
Zbyt wiele razy słyszałem krzyki przerażenia ze strony źle nakierowanych rm. Jak skrypt rm -fr $somepath/z somepathniezainicjowanym w nim. Mógłbym pójść dalej, by wyrazić, jak poważny to jest, ale zdecydowałem się pozostać przyjazny dla rodziny w moim napomnieniu.
DopeGhoti

3

To powinno zakończyć zadanie (choć nie w taki sam sposób, jak prosi OP):

ls -1 >1.txt
pico 1.txt 

usuń wszystkie pliki / katalogi, które chcesz zachować

xargs rm < 1.txt

Jeśli wszystkie pliki mają ten sam format nazwy, datę lub coś innego, istnieją inne metody.

Patrzę na i-węzły - i sprawdzam, czy są one sekwencyjne przez ls -i | sort, a jeśli tak, to nowe pliki będą miały większe i-węzły. Następnie stosując ten sam typ procesu jak powyżej ...

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

w powyższym poleceniu cięcia najpierw sprawdź listę i-węzłów, aby upewnić się, że jest to odpowiednia ilość.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.