¿Cómo puedo encontrar todos los archivos enlazados en un sistema de archivos?

21

Necesito encontrar todos los archivos enlazados en un sistema de archivos determinado. Por ejemplo, obtenga una lista de archivos, cada línea contiene pares vinculados, o trillizos, etc.

Entiendo más o menos cómo hacerlo, es necesario crear un diccionario con clave de inodo para todos los archivos / directorios en un sistema de archivos, excluir "." y enlaces "..", y luego indodes con más de un nombre son enlaces duros ... Pero espero que tal vez exista una solución preparada, o que alguien ya haya escrito dicho script.

haimg
fuente

Respuestas:

17

Puede ejecutar el siguiente comando:

find / -type f -printf '%n %p\n' | awk '$1 > 1{$1="";print}'

para encontrar todos los archivos vinculados.

O la versión @mbafford:

find / -type f -links +1 -printf '%i %n %p\n'
Gilles Quenot
fuente
1
Gracias, esto no es exactamente lo que quería, pero lo suficientemente cerca. Puedo agregar '% i' para imprimir los números de inodo y luego ordenar / agrupar por él ...
haimg
15
Puede evitar la necesidad de awk utilizando la sintaxis "-links + n 'de find. Por ejemplo, para encontrar todos los archivos con al menos dos enlaces e imprimir la información necesaria:find / -type f -links +1 -printf '%i %n %p\n'
mbafford
¿ Qué hay de pasar a través de sort(+ uniq)? Tenía curiosidad, así que lo probé en mi computadora principal (16GB i5-2500k con ssd). con 2187757 archivos ( find / -xdev -type f | wc) tarda 12 segundos reales al devolver 3820 archivos / 570 inodes ( time sudo find / -xdev -type f -links +1 -printf "%i\n" | sort | uniq | wc). necesitaría incluir el %n %ppara los archivos reales ya que los saqué para contar inodos.
Northern-bradley
17
find . -type f -links +1 2>/dev/null

proporciona una lista de todos los archivos que tienen más de un enlace, es decir, archivos para los que existe un enlace duro. Recorrer esto es relativamente fácil: una solución hacky si no tienes tantos archivos sería

for i in $(find . -type f -links +1 2>/dev/null); do find -samefile $i | awk '{printf "%s ", $1}'; printf "\n"; done | sort | uniq

Pero sinceramente espero que haya mejores soluciones, por ejemplo, dejando que la primera findllamada imprima números de inodo y luego usando findla -inumopción para mostrar todos los archivos asociados con este inodo.

Claudio
fuente
1
¡Ay! Esto escanea el sistema de archivos una y otra vez para cada archivo
vinculado
1
No dije que fuera rápido, y que funciona para pequeños árboles de directorios. Por supuesto, un índice adecuado, que podría construirse a partir de, por ejemplo, la salida de find . -type f -printf '%i %p\n', permitiría construir una solución mucho más rápida.
Claudio
Y eso no maneja el espacio en el camino AFAIK.
Gilles Quenot
Para el forbucle, ajustar IFS en consecuencia funcionaría. Para analizar el resultado del comando find en mi comentario, declarar que todo entre el primer espacio y el final de la línea como el nombre del archivo también debería funcionar.
Claudio
1
@Sati: asegura que los mensajes de error se descarten (por ejemplo, para carpetas a las que no tiene acceso, lost+foundetc.); lo cual es especialmente importante, si la salida debe procesarse más como en la segunda línea.
DJCrashdummy
1

En mi humilde opinión, la mejor manera es usar la siguiente línea (seguro que tienes que reemplazar /PATH/FOR/SEARCH/con lo que quieras buscar):

find /PATH/FOR/SEARCH/ -xdev -printf '%i\t%n\t%p\n' | fgrep -f <(find . -xdev -printf '%i\n' | sort -n | uniq -d) | sort -n

esto escanea el sistema de archivos solo una vez, muestra el inodo, el número de enlaces duros y la ruta de los archivos con más de un enlace duro y los ordena de acuerdo con el inodo.

Si le molestan los mensajes de error de las carpetas que no puede leer, puede expandir la línea a esto:

find /PATH/FOR/SEARCH/ -xdev -printf '%i\t%n\t%p\n' 2> /dev/null | fgrep -f <(find . -xdev -printf '%i\n' 2> /dev/null | sort -n | uniq -d) | sort -n
DJCrashdummy
fuente