Excluir ciertos archivos y directorios al eliminar archivos

11

Mi directorio de nivel superior es data. dataincluye varios directorios y estos directorios tienen subdirectorios. Necesito eliminar todos los archivos y directorios dentro, data/excepto varios archivos en algunos directorios.

Por ejemplo, los datos incluyen los directorios 100y 101. Yo sólo quiero seguir a.txty b.txtarchivos en 100/y c.txty d.txtarchivos en 101/mientras se quita todos los demás archivos y directorios en 100y 101.

Ejemplo:

.
├── 100
   ├── a.txt
   ├── b.txt
   ├── c.txt
   └── d.txt
└── 101
    ├── a.txt
    ├── b.txt
    ├── c.txt
    └── d.txt

Uso el rm -rf !(a.txt|b.txt)comando pero no puedo aplicar este comando para cada directorio automáticamente.

azul profundo
fuente

Respuestas:

12

Como ya descubrió, puede usar la extglobfunción que está habilitada con:

shopt -s extglob

Esto permite excluir coincidencias para que pueda hacer cosas como:

rm 100/!([ab].txt) 101/!([cd].txt)

Es una buena idea probarlo echoprimero. Este ejemplo coincidirá con cualquier cosa dentro de lo 100/que no sea a.txto b.txty cualquier cosa dentro de lo 101/que no sea c.txto d.txt. Si las mismas reglas se 100/aplican 102/también, puede hacerlo, por ejemplo:

10[02]/!([ab].txt) # or
{100,102}/!([ab].txt)
postre
fuente
Acabo de dar un ejemplo para 100 y 101 directorios, pero en realidad el número de subdirectorios es casi 20. ¿Hay alguna forma de implementar el código anterior para cada directorio sin escribir cada nombre de directorio en la carpeta principal?
Deepblue
@deepblue Proporcione un ejemplo exacto para eso en su pregunta ( editar ), no está especialmente claro cómo rmdebe saber qué archivos mantener en qué directorios si no desea especificar eso.
postre el
7

Podrías usar findpara esto. Puede negar las pruebas findcon -noto !. Esto excluirá coincidencias, en lugar de encontrarlas.

Debe tener cuidado de no eliminar ninguno de los directorios principales de los archivos que desea conservar, especialmente el directorio actual . , por lo que debe asegurarse de leer detenidamente el resultado antes de eliminarlo.

Según su ejemplo, podría hacer algo así desde el datadirectorio.

find ! -path . ! -path ./100 ! -path ./101 ! -path "./100/[ab].txt" ! -path "./101/[cd].txt"

Agregue un ! -path ./path/to/dirpara cualquier ruta que desee evitar eliminar. Puede usar metacaracteres como *, pero asegúrese de citar la expresión si lo hace, por ejemplo "./path*dir", para evitar expansiones no deseadas.

findes recursivo por defecto. Incluso si no encontramos ./100aquí, encontraremos todo su contenido a menos que coincidan con el patrón [ab].txt. Si no puede coincidir con todos los nombres que desea conservar, agregue otra prueba:

! -path "./100/[ab].txt" ! -path ./100/foo

Esto no encontrará a.txto b.txto foo, pero encontrará todos los demás archivos.

Cuando esté seguro de ver lo que quiere, puede agregar -deleteal final para eliminar los archivos encontrados:

find ! -path . ! -path ./100 ! -path ./101 ! -path "./100/[ab].txt" ! -path "./101/[cd].txt" -delete
Zanna
fuente