Come escludere alcuni file dal meccanismo di espansione del nome file in bash?


14

Ho directory di file system ubuntu nella directory root e ho copiato accidentalmente centinaia di file nella directory root.

Ho intuitivamente provato a rimuovere i file copiati escludendo il file system come

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

ma non funziona. Qual è il modo corretto di escludere alcune directory durante l'eliminazione dell'intero?

EDIT: Non provare mai nessuno dei comandi qui senza sapere cosa fare!


1
Che shell stai usando? Il globbing del nome del file dipende dalla shell quando si tratta di fare cose fantasiose come quelle.
Kusalananda

2
Non una risposta, ma vorrei usare per esempio mc. Seleziona tutto con *, quindi deseleziona i file specifici con -o il Inserttasto.
pbm,

1
Puoi spiegare cos'è "mc"?
MikeP,

@Kusalananda è/bin/bash
kenn

3
@MikeP: mcè Midnight Commander, un'imitazione molto utile di Norton Commander. Funziona in un terminale. (Sia Midnight Commander che Norton Commander sono esempi di quello che viene chiamato un file manager ortodosso .)
AlexP

Risposte:


21

Dal momento che stai usando bash:

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

Raccomando di aggiungere echoall'inizio della riga di comando quando si esegue qualcosa che potenzialmente può far saltare in aria l'intero sistema. Rimuovilo se sei soddisfatto del risultato.

Nota: il comando sopra non rimuove i file nascosti (quelli il cui nome inizia con un punto). Se vuoi rimuoverli, attiva anche l' dotglobopzione:

shopt -s dotglob

L'ho usato per ripulire con successo il filesystem. All'inizio l'ho provato in una directory. Ho anche provato la rm -rf ./!(bin,sbin,..)virgola separata, ma rimuove tutte le directory.
Kenn

Cos'è questa !(...)sintassi? Dall'esempio ho pensato intuitivamente di ls ./!(*/)elencare solo i file, ma non funziona in questo modo.
giusti,

@giusti Questa sintassi è una corrispondenza estesa del modello nel meccanismo di espansione del nome file: la descrizione è disponibile nel manuale bash nel capitolo Espansione percorso. Non può essere utilizzato per escludere i tipi di file, solo i nomi, proprio come con le stelle *o altri globs.
Jimmij,

12

Questo comando mostrerà tutte le non directory in /:

find / -maxdepth 1 -type f

Dopo esserti assicurato assolutamente che non ci siano file che desideri conservare, puoi utilizzare:

find / -maxdepth 1 -type f -delete

Più sicuro, sarebbe di spostarli altrove per assicurarsi che non si stia eliminando qualcosa che si desidera conservare:

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

Se, oltre ai file, hai anche delle directory che hai aggiunto alla radice del filesystem, questo potrebbe essere automatizzato escludendo le directory LSB da un automatizzato mvo rm, ma onestamente, dal momento che abbiamo a che fare con lo spurgo delle cose nel radice del filesystem, ti consiglio vivamente di prendere in considerazione la possibilità di farlo manualmente, se possibile.

Se ciò non è possibile, qualcosa del genere potrebbe fare il trucco:

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

Una volta superato il test dell'urlo (ovvero il sistema funziona ancora e non si urla di angoscia), è possibile rimuovere il contenuto di /root/preserve/.

Nota importante: qualunque cosa tu faccia, non pensare nemmeno di eseguire alcuna permutazione di rm -fr [ANYTHING GOES HERE] /.


la tua soluzione elimina solo i file ma ci sono anche cartelle in giro.
Kenn

1
Troppe volte, ho sentito grida di sgomento da un mal mirato rm. Come uno script con rm -fr $somepath/con somepathinizializzato in esso. Avrei potuto andare oltre nell'esprimere quanto grave fosse, ma ho optato per rimanere amico della famiglia nella mia ammonizione.
DopeGhoti,

3

Questo dovrebbe portare a termine il lavoro (anche se non nello stesso modo richiesto dall'OP):

ls -1 >1.txt
pico 1.txt 

rimuovere tutti i file / directory che si desidera conservare

xargs rm < 1.txt

Se tutti i tuoi file hanno lo stesso formato nome, data o qualcos'altro, allora ci sono altri metodi.

Guarderei gli inode - e vedrei se sono sequenziali tramite ls -i | sort e se lo sono, allora i nuovi file avranno inode più grandi. Quindi utilizzando lo stesso tipo di processo come sopra ...

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

nel comando cut sopra, controlla prima la tua lista degli inode per assicurarti che sia la giusta quantità.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.