Eliminar todos los archivos en una carpeta excepto los archivos X, Y y Z

17

Tengo muchos archivos y carpetas en una carpeta específica y quiero eliminarlos todos; Sin embargo, quería mantener los archivos X, Y y Z.

¿Hay alguna manera de que pueda hacer algo como: rm * | but NOT grep | X or Y or Z

Amit
fuente
¿Asumo que puedo usar alguna expresión regular allí que haga esto?
Amit

Respuestas:

16

En lugar de usar rm, puede ser más fácil usar find . Un comando como este eliminaría todo excepto un archivo llamado exactamente 'archivo'

find . \! -name 'file' -delete

Muchas versiones de deberían ser compatibles con el globing y la coincidencia de expresiones regulares.

También puede canalizar la salida de find a rm también

find . \! -name '*pattern*' -print0 | xargs --null rm 
Zoredache
fuente
3
Y esto le permite ver exactamente qué archivos se eliminarán al eliminar -deletey qué archivos se guardarán al eliminar -deletey \!.
Shawn J. Goff
1
cuidado, findes recursivo! por lo que todos los subdirectorios de archivos que no coincidan con el ' patrón ' también se eliminarán
Alexandre Holden Daly
La forma a través de xargs necesita -profundidad, para evitar el intento de eliminar directorios antes de que los archivos se incluyan en ellos. Sin embargo, creo que rm tampoco eliminará directorios.
usuario desconocido
9

Usando zsh, con setopt EXTENDED_GLOB, usando el ~operador ( excepto )

rm -- *~(x|y|z)

u ^operador (negación):

rm -- ^(x|y|z)

Pero, probablemente debería mover los archivos a otra parte, luego eliminar todo. Es mucho más seguro en términos de deslizamientos de los dedos, como presionar enter demasiado pronto.

wnoise
fuente
5

Las versiones posteriores de bash tienen la extglobopción de shell que le brinda una sintaxis para hacer lo que desea (consulte su página de manual en "Expansión del nombre de ruta" para ver si su versión instalada la tiene):

$ shopt -s extglob  # turn on extended globbing
$ rm !(X|Y|Z)

Para probar, le sugiero que primero reemplace rmcon echopara ver si la lista de archivos a eliminar es lo que espera.

camh
fuente
5
ls -1 | grep -v "^[XYZ]$" # | xargs rm -r

Atención: ejecute el comando y si los archivos que se van a eliminar son los correctos, ejecútelo nuevamente y elimine el carácter hash "#".

Si los nombres de archivo son más complicados que eso, haz

ls -1 | egrep -v "^file1$|^filename2$|^f1le$" # | xargs rm -r

Nuevamente, primero mire los resultados y luego elimine el signo hash.

Esta versión, como se sugiere en los comentarios, guarda algunos caracteres y se ve un poco más clara.

ls -1 | egrep -v "^(file1|filename2|f1le)$" # | xargs rm -r
ddeimeke
fuente
Una edición sugerida por ddeimeke es cambiar el egrepargumento a"^(file1|filename2|f1le)$"
Michael Mrozek
Si tiene tres archivos a, by a bel primer programa se eliminará, si coloca ab en la parte grep: "^[ab]$" ay bno a b, simplemente se opone a sus intenciones. El segundo comando hará lo mismo. Y el tercero también. No debe usar 'ls' en los scripts, con muy, muy raras excepciones. Solo no lo hagas.
Usuario desconocido
3

Mueva los archivos que desea mantener alejados. Suba un nivel, elimine la carpeta. Vuelva a crear la carpeta y mueva esos archivos hacia atrás.

alex
fuente
Me pregunto por qué el signo menos ... En realidad, es más fácil y seguro que cualquier cosa propuesta por otros: simplemente no puedes dispararte a ti mismo con un char especial en el nombre del archivo.
alex
a) Mueves tu archivo X un directorio hacia arriba, donde existe un archivo X - eliminado silenciosamente, desaparecido. b) Estás en el directorio superior, donde no existe 'arriba'. c) Estás en tu casa y no tienes permiso para escribir en / home. Si pone su consejo en un guión, lo probó sin problemas y lo usa en tal situación, ¡peng!
Usuario desconocido
2
a) Oye, ¿dije 'mover archivos hasta un nivel'? He dicho que los aleje. b) Entonces estás tratando de eliminar todos los archivos /, ¿eh? No muy practico. c) Intentar eliminar todos los archivos en tu $HOMEtampoco es realmente práctico.
alex
Tienes razón, lo siento.
Usuario desconocido
0

Esto es lo que configuré como un script .sh para un enlace de cierre de sesión OSX / MacOS, funciona bastante bien.

#! /bin/bash
for dir in /PathToFolder/*
 do
    if [ ! "$dir" = "/PathToFolder/FolderToKeep1" ] && [ ! "$dir" = "/PathToFolder/FolderToKeep2" ] && [ ! "$dir" = "/PathToFolder/FolderToKeep3" ] && [ ! "$dir" = "/PathToFolder/FolderToKeep4" ] && [ ! "$dir" = "/PathToFolder/FolderToKeep5" ] && [ ! "$dir" = "/PathToFolder/FolderToKeep6" ] ; then 
      echo ${dir}
      sudo rm -R $dir user
      dscl . -delete $dir
    fi 
  done

exit 0
ICMP
fuente
0

Con GNU-find puede usar el modificador -delete, que también elimina los directorios, si están vacíos:

 find tmp -not -name X -not -name Y -not -name Z -delete 
usuario desconocido
fuente
Si X, Y o Z es un directorio, esto también eliminará los archivos dentro de ellos. find tmp -maxdepth 1 -not -name X -not -name Y -not -name Z -deletees una forma de evitar esto.
Gilles 'SO- deja de ser malvado'
Dado que las carpetas en Unix son archivos (cualquier cosa es un archivo), tal vez eso es lo que se pretende. La pregunta dice explícitamente: "Tengo muchos archivos y carpetas en una carpeta específica y quiero eliminarlos todos"; y si desea excluir Y, tal vez sepa si Y es un directorio o no.
Usuario desconocido
Eso también se eliminará tmpsi no hubiera archivos X/ Y/ Zen él. Note !como el equivalente estándar de GNU -not( -deletetambién es una extensión de GNU)
Stéphane Chazelas
@ StéphaneChazelas: De la pregunta, eliminar carpetas (todas ellas) es lo que se solicitó. Como la explosión necesita enmascararse, prefiero escribir -no. Puede depender de la distribución del teclado alemán, donde Backslash necesita Alt-Gr.
usuario desconocido