
Tengo el siguiente problema. Tengo una estructura de directorios y quiero eliminar todo lo que está dentro de un directorio llamado Caches
. Todo debe eliminarse excepto todos los directorios nombrados Snapshots
. No puedo entender cómo hacer esto conencontraro cualquier otro comando que conozca.
El motivo por el que pregunto: en iOS, cada aplicación tiene su propio directorio de cachés. A veces, estos no se borran correctamente, según la aplicación. Con la solución a esta respuesta, se podrían borrar los cachés en iOS y, por lo tanto, optimizar el espacio en disco cuando la unidad del dispositivo esté montada en otra computadora, por ejemplo, con FUSE (iExplorer).
Esto es lo que tengo hasta ahora:
find . 2>/dev/null -type d -name "Caches" -maxdepth 3 -print
Esto devuelve algo como:
./Library/Caches
Cuando hago un ls ./Library/Caches
veo todos los contenidos y el Snapshots
directorio, que quiero excluir porque en última instancia quiero -delete
todo menos este.
Quiero algo como esto:
Before: After:
. .
├── a ├── a
│ ├── a │ ├── a
│ └── Caches │ └── Caches
│ ├── a │ └── a
│ │ └── Snapshots │ └── Snapshots
│ │ └── a │ └── a
│ ├── b └── b
│ │ └── a └── c
│ └── c
└── b
├── c
└── Caches
├── a
│ └── foo
│ └── a
└── b
└── a
Respuesta1
Estoy un poco confundido por la redacción de la pregunta. Si lo que quieres hacer es eliminar todo lo que hay en el ./Library/Caches
directorio excepto una única carpeta llamada Snapshots
, no es necesario utilizar find
. En bash
, los globos de shell son la forma más sencilla:
shopt -s extglob # probably already enabled
echo Library/Caches/!(Snapshots)
Si esto imprime todos los archivos/directorios que desea eliminar, reemplácelos echo
por rm -f --
.
Si hay varios Snapshots
directorios en diferentes niveles del árbol de directorios a continuación ./Library/Caches
que desea conservar, entonces con GNU find
puede hacerlo:
find Library/Caches ! -path '*Snapshots*'
Esto debería imprimir todos los archivos/directorios excepto aquellos que se encuentran Snapshots
en su ruta. Incluirá directorios que contienen (o cuyos hijos contienen) Snapshots
directorios, sin embargo, find ... -delete
no los eliminará y en su lugar imprimirá un error que indica que no están vacíos. Una vez que esté satisfecho, agréguelo -delete
al final.
Una advertencia es que esto dejará cualquierarchivosnombrado Snapshots
intacto. Si esto es un problema, en su lugar haga:
find Library/Caches \( ! -path '*Snapshots*' -o -type f -name Snapshots \)
Nuevamente agregue -delete
cuando esté satisfecho.
Respuesta2
find . -depth -print0 | perl -0lne '
if ("$_/" =~ m{/Caches(/.*)}s && $1 !~ m{/Snapshots/}) {rmdir $_ or unlink $_}'
Si find
no lo admite -print0
, puede reemplazarlo con -exec printf '%s\0' {} +
.
La idea es imprimir la lista de archivos terminados en NUL (ya que 0 es el único byte que no puede ocurrir en una ruta de archivo) y usar la opción perl
's -n
con -0
para ejecutar algún código para cada uno de esos nombres de archivo (con $_
el nombre de archivo configurado ). ).
Con -depth
, los archivos se imprimen antes de su directorio principal. Solo eliminamos archivos o directorios (suponiendo que estén vacíos, por eso es importante procesar la lista en depth
orden) si su ruta /Caches/
no contiene seguido de /Snapshosts/
.
Respuesta3
No soy un find
hechicero, así que no quiero decir que no puedas hacerlo find
, pero sí sé que se puede hacer con un par de líneas de bash
. Dado que entiendo correctamente la estructura de su directorio:
#!/bin/bash
for i in Library/Caches/*; do
if [[ -d "$i" ]]; then
[[ "$i" =~ "Snapshots" ]] || echo "rm-ing $i" # change to rm -rf "$i" to use
fi
done
La for
declaración devuelve cada elemento en Library/Caches/
. La if [[ -d "$i" ]]
declaración verifica que cada elemento sea un directorio y, si lo es, se verifica su nombre para ver si contiene "instantáneas" [[ "$i" =~ "Snapshots" ]]
. Debido a que no hay un operador para negar una coincidencia de expresiones regulares, como !=~
, solía ||
ejecutar rm
si el comando anterior no tenía éxito, por ejemplo, el nombre del directorio no contiene instantáneas.
Esto se ejecutará en cualquier sistema moderno que utilice bash
, pero debe tener bash
. Además, es posible que necesites jugar con la estructura del directorio, pero eso debería ser suficiente.
Respuesta4
Primera parte: busque directorios llamados cachés y haga algo con ellos
find . -name Caches -type d -exec … \;
Segunda parte: recorrer un directorio de caché y eliminar todo, pero conservar Snapshots
los subdirectorios y su contenido (así como las rutas que conducen a ellos). Realice un recorrido en profundidad para que los directorios se puedan eliminar una vez que queden vacíos.
find /path/to/Caches -depth -name Snapshots -type d -prune \
-o \( -type d -empty -o ! -type d \) -delete
Ahora combínalos.
find . -name Caches -type d -exec
find {} -depth -name Snapshots -type d -prune \
-o \( -type d -empty -o ! -type d \) -delete