¿Cómo excluir algunos archivos del mecanismo de expansión de nombre de archivo en bash?

14

Tengo directorios del sistema de archivos ubuntu en el directorio raíz y accidentalmente copié cientos de archivos en el directorio raíz.

Intenté intuitivamente eliminar archivos copiados excluyendo el sistema de archivos como

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

Pero no funciona. ¿Cuál es la forma correcta de excluir algunos directorios mientras se elimina el conjunto?

EDITAR: ¡ Nunca intentes ninguno de los comandos aquí sin saber qué hacer!

Kenn
fuente
1
¿Qué caparazón estás usando? El globbing de nombre de archivo depende de la shell cuando se trata de hacer cosas elegantes como esa.
Kusalananda
2
No es una respuesta, pero usaría por ejemplo mc. Seleccione todo con *, luego deseleccione archivos específicos con -o la Inserttecla.
pbm
1
¿Puedes explicar qué es 'mc'?
MikeP
@Kusalananda es/bin/bash
kenn
3
@MikeP: mces Midnight Commander, una imitación muy útil de Norton Commander. Se ejecuta en una terminal. (Tanto Midnight Commander como Norton Commander son ejemplos de lo que se llama un administrador de archivos ortodoxo ).
AlexP

Respuestas:

21

Como estás usando bash:

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

Recomiendo agregar echoal comienzo de la línea de comando cuando esté ejecutando algo que potencialmente puede hacer explotar todo el sistema. Elimínelo si está satisfecho con el resultado.

Nota: El comando anterior no eliminará los archivos ocultos (aquellos cuyo nombre comienza por un punto). Si desea eliminarlos también, active también la dotglobopción:

shopt -s dotglob
jimmij
fuente
Lo usé para limpiar el sistema de archivos con éxito. Al principio lo probé en un directorio. También intenté rm -rf ./!(bin,sbin,..)separados por comas, pero elimina todos los directorios.
kenn
¿Cuál es esa !(...)sintaxis? Del ejemplo, pensé intuitivamente ls ./!(*/)que solo incluiría una lista de archivos, pero no funciona de esa manera.
giusti
@giusti Esta sintaxis es una coincidencia de patrón extendida en el mecanismo de expansión de nombre de archivo; encontrará su descripción en el manual de bash en el capítulo Expansión de nombre de ruta. No se puede usar para excluir tipos de archivos, solo nombres, al igual que con estrellas *u otros globos.
jimmij
12

Este comando mostrará todos los no directorios en /:

find / -maxdepth 1 -type f

Una vez que se haya asegurado absolutamente de que no hay archivos que desee conservar, puede usar:

find / -maxdepth 1 -type f -delete

Más seguro sería moverlos a otro lugar para asegurarse de que no está eliminando algo que desea conservar:

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

Si, además de los archivos, también tiene directorios que ha agregado a la raíz del sistema de archivos, esto podría automatizarse excluyendo los directorios LSB de un sistema automatizado mvo rm, honestamente, ya que estamos tratando de purgar cosas en el raíz del sistema de archivos, le sugiero encarecidamente que considere hacerlo manualmente si es posible.

Si esto no es factible, algo como esto podría hacer el truco:

#!/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 vez que haya pasado la prueba de gritos (es decir, su sistema aún se ejecuta y no grita con angustia), puede eliminar el contenido de /root/preserve/.

Nota importante: hagas lo que hagas, ni siquiera pienses en ejecutar ninguna permutación de rm -fr [ANYTHING GOES HERE] /.

DopeGhoti
fuente
su solución solo elimina archivos, pero también hay carpetas.
Kenn
1
Demasiadas veces, escuché chillidos de consternación por parte de un mal dirigido rm. Como un guión con rm -fr $somepath/sin somepathinicializar. Podría haber ido más lejos al expresar cuán grave es esto, pero opté por seguir siendo amigable con la familia en mi advertencia.
DopeGhoti
3

Esto debería hacer el trabajo (aunque no de la misma manera que el OP pregunta):

ls -1 >1.txt
pico 1.txt 

eliminar todos los archivos / directorios que desea mantener

xargs rm < 1.txt

Si todos sus archivos tienen el mismo formato de nombre, fecha u otra cosa, existen otros métodos.

Vería los inodes, y vería si son secuenciales a través de ls -i | sort y, si lo son, los nuevos archivos tendrán inodos más grandes. Luego, utilizando el mismo tipo de proceso que el anterior ...

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

en el comando de corte anterior, verifique primero su lista de inodes para asegurarse de que sea la cantidad correcta.

MikeP
fuente