TLDR: comprenda sus directorios raíz y adapte su búsqueda desde allí, utilizando la -path <excluded_path> -prune -o
opción No incluya un final/
al final de la ruta excluida.
Ejemplo:
find / -path /mnt -prune -o -name "*libname-server-2.a*" -print
Para utilizar de manera efectiva find
, creo que es imperativo tener una buena comprensión de la estructura de directorios de su sistema de archivos. En la computadora de mi casa tengo discos duros de TB múltiple, con aproximadamente la mitad de ese contenido respaldado usando rsnapshot
(es decir, rsync
). Aunque se realiza una copia de seguridad en una unidad físicamente independiente (duplicada), está montada en el /
directorio raíz ( ) de mi sistema /mnt/Backups/rsnapshot_backups/
:
/mnt/Backups/
└── rsnapshot_backups/
├── hourly.0/
├── hourly.1/
├── ...
├── daily.0/
├── daily.1/
├── ...
├── weekly.0/
├── weekly.1/
├── ...
├── monthly.0/
├── monthly.1/
└── ...
El /mnt/Backups/rsnapshot_backups/
directorio actualmente ocupa ~ 2.9 TB, con ~ 60 millones de archivos y carpetas; simplemente atravesar esos contenidos lleva tiempo:
## As sudo (#), to avoid numerous "Permission denied" warnings:
time find /mnt/Backups/rsnapshot_backups | wc -l
60314138 ## 60.3M files, folders
34:07.30 ## 34 min
time du /mnt/Backups/rsnapshot_backups -d 0
3112240160 /mnt/Backups/rsnapshot_backups ## 3.1 TB
33:51.88 ## 34 min
time rsnapshot du ## << more accurate re: rsnapshot footprint
2.9T /mnt/Backups/rsnapshot_backups/hourly.0/
4.1G /mnt/Backups/rsnapshot_backups/hourly.1/
...
4.7G /mnt/Backups/rsnapshot_backups/weekly.3/
2.9T total ## 2.9 TB, per sudo rsnapshot du (more accurate)
2:34:54 ## 2 hr 35 min
Por lo tanto, cada vez que necesito buscar un archivo en mi /
partición (raíz), necesito tratar (evitar si es posible) atravesar mi partición de copias de seguridad.
EJEMPLOS
Entre los abordados sugeridos de diversas maneras en este hilo ( Cómo excluir un directorio en el comando find. ), Encuentro que las búsquedas que usan la respuesta aceptada son mucho más rápidas, con advertencias.
Solución 1
Digamos que quiero encontrar el archivo del sistema libname-server-2.a
, pero no quiero buscar entre mis rsnapshot
copias de seguridad. Para encontrar rápidamente un archivo del sistema, use la ruta de exclusión /mnt
(es decir, use /mnt
, not /mnt/
, or /mnt/Backups
, or ...):
## As sudo (#), to avoid numerous "Permission denied" warnings:
time find / -path /mnt -prune -o -name "*libname-server-2.a*" -print
/usr/lib/libname-server-2.a
real 0m8.644s ## 8.6 sec <<< NOTE!
user 0m1.669s
sys 0m2.466s
## As regular user (victoria); I also use an alternate timing mechanism, as
## here I am using 2>/dev/null to suppress "Permission denied" warnings:
$ START="$(date +"%s")" && find 2>/dev/null / -path /mnt -prune -o \
-name "*libname-server-2.a*" -print; END="$(date +"%s")"; \
TIME="$((END - START))"; printf 'find command took %s sec\n' "$TIME"
/usr/lib/libname-server-2.a
find command took 3 sec ## ~3 sec <<< NOTE!
... encuentra ese archivo en solo unos segundos, mientras que esto toma mucho más tiempo (parece repetirse a través de todos los directorios "excluidos"):
## As sudo (#), to avoid numerous "Permission denied" warnings:
time find / -path /mnt/ -prune -o -name "*libname-server-2.a*" -print
find: warning: -path /mnt/ will not match anything because it ends with /.
/usr/lib/libname-server-2.a
real 33m10.658s ## 33 min 11 sec (~231-663x slower!)
user 1m43.142s
sys 2m22.666s
## As regular user (victoria); I also use an alternate timing mechanism, as
## here I am using 2>/dev/null to suppress "Permission denied" warnings:
$ START="$(date +"%s")" && find 2>/dev/null / -path /mnt/ -prune -o \
-name "*libname-server-2.a*" -print; END="$(date +"%s")"; \
TIME="$((END - START))"; printf 'find command took %s sec\n' "$TIME"
/usr/lib/libname-server-2.a
find command took 1775 sec ## 29.6 min
Solución 2
La otra solución ofrecida en este hilo ( SO # 4210042 ) también funciona mal:
## As sudo (#), to avoid numerous "Permission denied" warnings:
time find / -name "*libname-server-2.a*" -not -path "/mnt"
/usr/lib/libname-server-2.a
real 33m37.911s ## 33 min 38 sec (~235x slower)
user 1m45.134s
sys 2m31.846s
time find / -name "*libname-server-2.a*" -not -path "/mnt/*"
/usr/lib/libname-server-2.a
real 33m11.208s ## 33 min 11 sec
user 1m22.185s
sys 2m29.962s
RESUMEN | CONCLUSIONES
Utilice el enfoque ilustrado en la " Solución 1 "
find / -path /mnt -prune -o -name "*libname-server-2.a*" -print
es decir
... -path <excluded_path> -prune -o ...
teniendo en cuenta que cada vez que agrega el final /
a la ruta excluida, el find
comando ingresa recursivamente (todos esos) /mnt/*
directorios, lo que en mi caso, debido a los /mnt/Backups/rsnapshot_backups/*
subdirectorios, ¡también incluye ~ 2.9 TB de archivos para buscar! Al no agregar un final, /
la búsqueda debe completarse casi de inmediato (en segundos).
Del mismo modo, la "Solución 2" ( ... -not -path <exclude path> ...
) parece buscar recursivamente a través de los directorios excluidos, no devuelve coincidencias excluidas, pero consume innecesariamente ese tiempo de búsqueda.
Buscando dentro de esos rsnapshot
copias de seguridad:
Para encontrar un archivo en una de mis rsnapshot
copias de seguridad por hora / día / semana / mes ):
$ START="$(date +"%s")" && find 2>/dev/null /mnt/Backups/rsnapshot_backups/daily.0 -name '*04t8ugijrlkj.jpg'; END="$(date +"%s")"; TIME="$((END - START))"; printf 'find command took %s sec\n' "$TIME"
/mnt/Backups/rsnapshot_backups/daily.0/snapshot_root/mnt/Vancouver/temp/04t8ugijrlkj.jpg
find command took 312 sec ## 5.2 minutes: despite apparent rsnapshot size
## (~4 GB), it is in fact searching through ~2.9 TB)
Excluyendo un directorio anidado:
Aquí, quiero excluir un directorio anidado, por ejemplo, /mnt/Vancouver/projects/ie/claws/data/*
al buscar desde /mnt/Vancouver/projects/
:
$ time find . -iname '*test_file*'
./ie/claws/data/test_file
./ie/claws/test_file
0:01.97
$ time find . -path '*/data' -prune -o -iname '*test_file*' -print
./ie/claws/test_file
0:00.07
Aparte: Agregar -print
al final del comando suprime la impresión del directorio excluido:
$ find / -path /mnt -prune -o -name "*libname-server-2.a*"
/mnt
/usr/lib/libname-server-2.a
$ find / -path /mnt -prune -o -name "*libname-server-2.a*" -print
/usr/lib/libname-server-2.a