Utilice buscar para encontrar cierto directorio y eliminar todos los archivos que contiene excepto un directorio

Utilice buscar para encontrar cierto directorio y eliminar todos los archivos que contiene excepto un directorio

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/Cachesveo todos los contenidos y el Snapshotsdirectorio, que quiero excluir porque en última instancia quiero -deletetodo 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/Cachesdirectorio 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 echopor rm -f --.

Si hay varios Snapshotsdirectorios en diferentes niveles del árbol de directorios a continuación ./Library/Cachesque desea conservar, entonces con GNU findpuede 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) Snapshotsdirectorios, sin embargo, find ... -deleteno los eliminará y en su lugar imprimirá un error que indica que no están vacíos. Una vez que esté satisfecho, agréguelo -deleteal final.

Una advertencia es que esto dejará cualquierarchivosnombrado Snapshotsintacto. Si esto es un problema, en su lugar haga:

find Library/Caches \( ! -path '*Snapshots*' -o -type f -name Snapshots \)

Nuevamente agregue -deletecuando esté satisfecho.

Respuesta2

find . -depth -print0 | perl -0lne '
  if ("$_/" =~ m{/Caches(/.*)}s && $1 !~ m{/Snapshots/}) {rmdir $_ or unlink $_}'

Si findno 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 -ncon -0para 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 depthorden) si su ruta /Caches/no contiene seguido de /Snapshosts/.

Respuesta3

No soy un findhechicero, 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 fordeclaració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 rmsi 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 Snapshotslos 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

información relacionada