
Me gustaría buscar find
archivos (con características similares), pero seguir y seguir solo enlaces simbólicos específicos (por coincidencia de patrones).
Aparentemente find
no puede manejarlo por sí solo: no hay ninguna opción para configurar el comportamiento de seguimiento del enlace simbólico; y un find -L
bloqueo ingenuo que se activa fácilmente (o que es extremadamente lento).
Respuesta1
La última oración de la pregunta sugiere que el problema no está en seguir enlaces simbólicos en general (y, por ejemplo, aplicar -newer
al enlace simbólico en un caso, mientras que al objetivo en otro caso), sino en seguir enlaces simbólicos.a directoriosy así descender donde no quieres.
Porespecificación, find
detectará bucles infinitos, por lo que no debería ocurrir un bloqueo activo. La pérdida de recursos (incluido el tiempo) puede ser un problema y entiendo su preocupación.
En primer lugar, utilice -L
para permitir find
seguir los enlaces simbólicos que desea que siga. Entonces necesitas una forma de detectar otros enlaces simbólicos.
Nunca find -L
-type l
es cierto, pero puede detectar enlaces simbólicos -exec test -L {} \;
(recuerde -exec … \;
que también es una prueba, tiene éxito si el comando interno sale con el estado 0). De esta manera aún puedes aplicar algunas pruebas específicamente a los enlaces simbólicos y -prune
(o no) en consecuencia.
Por ejemplo, el siguiente comando descenderá solo enlaces simbólicos cuyos nombres comiencen foo
o terminen con bar
:
find -L . -exec test -L {} \; ! \( -name 'foo*' -o -name '*bar' \) -prune -o -print
Cualquier expresión que quisieras originalmente, colócala después -prune -o
. En el comando anterior, la expresión "original" es -print
. Recuerde -exec
que suprime el implícito -print
, por lo que si lo necesita -print
, agréguelo explícitamente (como lo hicimos nosotros).
Tenga en cuenta que -name
prueba el nombre del enlace simbólico. Si desea probar el nombre del objetivo, entonces necesita realpath
, posiblemente basename
, algún código de shell; ejemplo:
find -L . -exec test -L {} \; -exec sh -c '
case "$(basename "$(realpath "$1")")" in
baz* ) exit 0 ;;
*qux ) exit 1 ;;
esac
exit 0
' find-sh {} \; -prune -o -print
El comando anterior creará -prune
cualquier enlace simbólico a cualquier archivo cuyo nombre comience con baz
, pero descenderá los enlaces simbólicos a directorios con nombres que terminen en qux
(a menos que comiencen con baz
) y finalmente -prune
a todos los demás enlaces simbólicos.
Notas:
realpath
ybasename
no son portátiles.realpath
resuelve todos los enlaces simbólicos.- El comportamiento en caso de un enlace simbólico roto puede ser o no el esperado.
- Invocar un archivo separado
test
para cada archivo afectará el rendimiento, pero no he encontrado una manera mejor. Invocarsh
,realpath
ybasename
también es malo en este asunto, pero aquí ocurre solo para enlaces simbólicos, por lo que en la mayoría de los casos el impacto será limitado. find-sh
se explica aquí:¿Cuál es el segundo pezsh -c 'some shell code' sh
?- En los ejemplos, las rutas de acceso que obtienen
-prune
d no serán-print
ed. Cambie el fragmento final a-prune -false -o -print
y se imprimirán. Verexplicación; Hay una alternativa portátil-false
en caso de que la necesites.