Hay muchas situaciones en las que el uso de a *
es prácticamente inevitable, por ejemplo, rm -rf *
en una carpeta que contiene miles de subcarpetas y archivos.
Pero, ¿qué sucede si desea excluir solo uno o dos archivos o carpetas del rm
comando? Busqué en Google y solo encontré soluciones bastante complicadas, find . -depth -not \( -name 'one' -o -name 'two' \
-o -name 'three' \) -exec rm {} \;
como se indica aquí .
¿Existe la posibilidad de hacer esto de una manera más fácil, sin ese desvío find
? Por ejemplo, rm -rf --exclude='one' --exclude='two' --exclude='three' *
como en rsync o simplemente rm -rf -e 'one','two','three' *
?
Tal vez incluso una posibilidad general de excluir cosas de *
(por lo demás comandos como cp
, mv
, ... no tienen que poner en práctica su propia)? ¿Algo así *{'one','two','three'}
o algo así?
fuente
find
con la--delete
opción (no es necesario ejecutarrm
para cada archivo. Esa es una sobrecarga innecesaria).mv -t /tmp one two three && rm -rf * && mv -t . /tmp/one /tmp/two /tmp/three
, pero preferiría una solución que ofrezca la posibilidad de excluir explícitamente algo de*
. Seguramente habrá situaciones en las que mover o copiar los archivos a otro destino no será una opción.Respuestas:
Para Bash hay una opción de shell llamada
extglob
que está desactivada por defecto para mantener la compatibilidad con la sintaxis de shell estándar. Extglob complementa la sintaxis de los operadores adicionales como!()
,?()
,@()
y algunos más.Para encender
extglob
, escribashopt -s extglob
. Para mantenerlo encendido para el tipo de usuario actualecho 'shopt -s extglob' >> ~/.bashrc
.Para el ejemplo rm: Con
extglob
usted puede usarfuente
shopt
cosa en tu interior~/.bashrc
, no puede doler.*
, sino que agrega indicadores similares (como el!
) que tienen funciones adicionales. En ese caso, sería una solución encantadora.He construido excepto exactamente eso (sry que todavía no pude agregar documentación).
Tengo una carpeta como la siguiente:
Escribir
except b d
te daráa
yc
Ahora puedes canalizar eso a
rm
.Esto puede ser difícil de recordar, entonces, ¿por qué no solo construir un script encima de excepto, llamado
rm-except
:Del mismo modo fácil es
ls-except
:fuente
Como alternativa a extglob (aunque esa es una muy buena respuesta y todos deberían tenerla
shopt -s extglob globstar
en su .bashrc), puede usar la variable global $ GLOBIGNORE . Digamos que desea obtener todos los archivos excepto 'foo.txt' y 'bar baz.txt':... sin embargo, esto activará la opción de shell
dotglob
, lo que significa que*
coincidirá con los archivos que comienzan con un punto (que normalmente están ocultos). Entonces realmente necesitas dos comandos:Dado que esta es una variable global, afectará cada globo que use hasta que $ GLOBSTAR se desarme al cerrar sesión o con
También funcionará solo en las cadenas literales pasadas a la variable. Puede ver a qué me refiero estableciendo $ GLOBIGNORE y observando la diferencia entre estos comandos:
fuente