Corro
ln /a/A /b/B
Me gustaría ver en la carpeta a
donde están los puntos a presentar una por ls
.
linux
filesystems
hardlink
Léo Léopold Hertz 준영
fuente
fuente
link(2)
llamada al sistema, no tiene sentido cuál es el original y el enlace. Por eso, como señalan las respuestas, la única forma de encontrar todos los enlaces esfind / -samefile /a/A
. Porque una entrada de directorio para un inodo no "conoce" otras entradas de directorio para el mismo inodo. Todo lo que hacen es volver a contar el inodo para que se pueda eliminar cuando el apellido esunlink(2)ed
. (Este es el "conteo de enlaces" en lals
salida).Respuestas:
Puede encontrar el número de inodo para su archivo con
y
muestra el recuento de referencias (número de enlaces duros a un inodo particular)
Después de encontrar el número de inodo, puede buscar todos los archivos con el mismo inodo:
mostrará los nombres de archivo para inode NUM en el directorio actual (.)
fuente
Realmente no hay una respuesta bien definida a su pregunta. A diferencia de los enlaces simbólicos, los enlaces duros no se pueden distinguir del "archivo original".
Las entradas de directorio consisten en un nombre de archivo y un puntero a un inodo. El inodo a su vez contiene los metadatos del archivo y (apunta a) el contenido real del archivo). Crear un enlace duro crea otro nombre de archivo + referencia al mismo inodo. Estas referencias son unidireccionales (al menos en sistemas de archivos típicos): el inodo solo mantiene un recuento de referencias. No hay una forma intrínseca de averiguar cuál es el nombre de archivo "original".
Por cierto, esta es la razón por la cual se llama al sistema para "eliminar" un archivo
unlink
. Simplemente elimina un enlace duro. El inodo y los datos adjuntos se eliminan solo si el recuento de referencia del inodo cae a 0.La única forma de encontrar las otras referencias a un inodo dado es buscar exhaustivamente en el sistema de archivos comprobando qué archivos se refieren al inodo en cuestión. Puede usar 'prueba A -ef B' desde el shell para realizar esta verificación.
fuente
UNIX tiene enlaces duros y enlaces simbólicos (hechos con
"ln"
y"ln -s"
respectivamente). Los enlaces simbólicos son simplemente un archivo que contiene la ruta real a otro archivo y puede cruzar sistemas de archivos.Los enlaces duros han existido desde los primeros días de UNIX (que puedo recordar de todos modos, y eso se remonta bastante tiempo). Son dos entradas de directorio que hacen referencia a los exactos mismos datos subyacentes. Los datos en un archivo se especifican por su
inode
. Cada archivo en un sistema de archivos apunta a un inodo, pero no es necesario que cada archivo apunte a un inodo único, de ahí provienen los enlaces duros.Dado que los inodos son únicos solo para un sistema de archivos dado, existe una limitación de que los enlaces duros deben estar en el mismo sistema de archivos (a diferencia de los enlaces simbólicos). Tenga en cuenta que, a diferencia de los enlaces simbólicos, no hay un archivo privilegiado, todos son iguales. El área de datos solo se liberará cuando se eliminen todos los archivos que usan ese inodo (y todos los procesos también lo cierran, pero ese es un problema diferente).
Puede usar el
"ls -i"
comando para obtener el inodo de un archivo en particular. Luego puede usar el"find <filesystemroot> -inum <inode>"
comando para buscar todos los archivos en el sistema de archivos con ese inodo dado.Aquí hay un script que hace exactamente eso. Lo invocas con:
y encontrará todos los archivos en ese sistema de archivos que son enlaces duros para ese archivo:
Aquí está el guión.
fuente
. ./findhardlinks.bash
mientras estoy en Zsh de OS X. Mi ventana actual en la pantalla se cierra.INUM=$(stat -c %i $1)
. TambiénNUM_LINKS=$(stat -c %h $1)
. Consulteman stat
para ver más variables de formato que puede usar.La primera columna representará los permisos. La segunda columna será el número de subelementos (para directorios) o el número de rutas a los mismos datos (enlaces duros, incluido el archivo original) al archivo. P.ej:
fuente
inode
que a su vez apunta al contenido del disco.¿Qué tal el siguiente más simple? (¡Este último podría reemplazar los largos guiones de arriba!)
Si tiene un archivo específico
<THEFILENAME>
y desea conocer todos sus enlaces rígidos distribuidos en el directorio<TARGETDIR>
(que incluso puede ser todo el sistema de archivos indicado por/
)Extendiendo la lógica, si desea conocer todos los archivos que
<SOURCEDIR>
tienen múltiples enlaces duros distribuidos en<TARGETDIR>
:fuente
-type f
porque el archivo también puede ser un directorio..
y..
en los directorios son enlaces duros. Puede saber cuántos subdirectores hay en un directorio a partir del recuento de enlaces de.
. Esto es discutible de todos modos, ya quefind -samefile .
todavía no imprimirá ningúnsubdir/..
resultado.find
(al menos la versión GNU) parece ser difícil de ignorar..
, incluso con-noleaf
.O(n^2)
, y se ejecutafind
una vez para cada miembro de un conjunto de archivos vinculados.find ... -printf '%16i %p\n' | sort -n | uniq -w 16 --all-repeated=separate
funcionaría, (16 no es lo suficientemente ancho para una representación decimal de 2 ^ 63-1, por lo que cuando su sistema de archivos XFS es lo suficientemente grande como para tener números de inodo tan altos, tenga cuidado)Hay muchas respuestas con scripts para encontrar todos los enlaces duros en un sistema de archivos. La mayoría de ellos hacen cosas tontas como ejecutar find para escanear todo el sistema de archivos en
-samefile
busca de CADA archivo con enlaces múltiples. Esto es Loco; todo lo que necesita es ordenar el número de inodo e imprimir duplicados.Con solo una pasada sobre el sistema de archivos para buscar y agrupar todos los conjuntos de archivos enlazados
Esto es mucho más rápido que las otras respuestas para encontrar múltiples conjuntos de archivos enlazados.
find /foo -samefile /bar
es excelente para solo un archivo.-xdev
: límite a un sistema de archivos. No es estrictamente necesario ya que también imprimimos el FS-id para uniq en! -type d
rechazar directorios: las entradas.
y..
significan que siempre están vinculados.-links +1
: enlace cuenta estrictamente> 1
-printf ...
imprime FS-id, número de inodo y ruta. (Con relleno para anchos de columna fijos de los que podemos hablaruniq
).sort -n | uniq ...
ordenación numérica y uniquificación en las primeras 42 columnas, separando grupos con una línea en blancoEl uso
! -type d -links +1
significa que la entrada de clasificación es tan grande como la salida final de uniq, por lo que no estamos haciendo una gran cantidad de clasificación de cadenas. A menos que lo ejecute en un subdirectorio que solo contiene uno de un conjunto de enlaces duros. De todos modos, esto usará MUCHO menos tiempo de CPU para volver a recorrer el sistema de archivos que cualquier otra solución publicada.salida de muestra:
TODO ?: descomprime la salida con
awk
ocut
.uniq
tiene un soporte de selección de campo muy limitado, por lo que relleno la salida de búsqueda y uso ancho fijo. 20 caracteres es lo suficientemente ancho para el máximo número posible de inodo o dispositivo (2 ^ 64-1 = 18446744073709551615). XFS elige los números de inodo según el lugar del disco en el que están asignados, no contiguamente desde 0, por lo que los sistemas de archivos XFS grandes pueden tener números de inodo> 32 bits incluso si no tienen miles de millones de archivos. Otros sistemas de archivos pueden tener números de inodo de 20 dígitos, incluso si no son gigantes.TODO: ordena los grupos de duplicados por ruta. Tenerlos ordenados por punto de montaje y luego número de inodo mezcla cosas juntas, si tiene un par de subdirecciones diferentes que tienen muchos enlaces duros. (es decir, grupos de grupos dobles van juntos, pero la salida los mezcla).
Una final
sort -k 3
ordenaría las líneas por separado, no grupos de líneas como un solo registro. El preprocesamiento con algo para transformar un par de líneas nuevas en un byte NUL, y el uso de GNUsort --zero-terminated -k 3
podría ser el truco.tr
Sin embargo, solo funciona con caracteres individuales, no con patrones 2-> 1 o 1-> 2.perl
lo haría (o simplemente analizar y ordenar dentro de perl o awk).sed
También podría funcionar.fuente
%D
es el identificador de sistema de archivos (que es único para el inicio actual, mientras que no hay sistemas de ficheros seumount
ed), por lo siguiente es incluso más genérica:find directories.. -xdev ! -type d -links +1 -printf '%20i %20D %p\n' | sort -n | uniq -w 42 --all-repeated=separate
. Esto funciona siempre que ningún directorio dado contenga otro directorio en el nivel del sistema de archivos, también analiza todo lo que se puede vincular (como dispositivos o enlaces programables; sí, los enlaces programables pueden tener un recuento de enlaces mayor que 1). Tenga en cuenta quedev_t
yino_t
tiene 64 bits de largo hoy. Esto probablemente se mantendrá mientras tengamos sistemas de 64 bits.! -type d
, en lugar de-type f
. Incluso tengo algunos enlaces simbólicos enlazados en mi sistema de archivos por organizar algunas colecciones de archivos. Actualicé mi respuesta con su versión mejorada (pero puse el id de fs primero, por lo que el orden de clasificación al menos se agrupa por sistema de archivos)Esto es algo así como un comentario a la propia respuesta y guión de Torocoro-Macho, pero obviamente no cabe en el cuadro de comentarios.
Reescribió su script con formas más directas de encontrar la información y, por lo tanto, muchas menos invocaciones de proceso.
Traté de mantenerlo lo más similar posible al suyo para facilitar la comparación.
Comentarios sobre este script y el tuyo
Uno siempre debe evitar la
$IFS
magia si un globo es suficiente, ya que es innecesariamente complicado, y los nombres de los archivos pueden contener nuevas líneas (pero en la práctica, principalmente, la primera razón).Debe evitar el análisis manual
ls
y la salida de este tipo tanto como sea posible, ya que tarde o temprano lo morderá. Por ejemplo: en su primeraawk
línea, falla en todos los nombres de archivos que contienen espacios.printf
a menudo ahorrará problemas al final ya que es muy robusto con la%s
sintaxis. También le brinda control total sobre la salida, y es consistente en todos los sistemas, a diferenciaecho
.stat
puede ahorrarle mucha lógica en este caso.GNU find
es poderosoSus invocaciones
head
ytail
podrían haberse manejado directamenteawk
con, por ejemplo, elexit
comando y / o la selección en laNR
variable. Esto ahorraría invocaciones de procesos, que casi siempre mejoran severamente el rendimiento en scripts de trabajo duro.Tu
egrep
s bien podría ser justogrep
.fuente
find ... -xdev -type f -links +1 -printf '%16i %p\n' | sort -n | uniq -w 16 --all-repeated=separate
. Esto es MUCHO más rápido, ya que solo atraviesa el fs una vez. Para múltiples FSes a la vez, necesitará prefijar los números de inodo con una identificación FS. Quizás confind -exec stat... -printf ...
Basado en el
findhardlinks
script (renombrado comohard-links
), esto es lo que he refactorizado y lo hice funcionar.Salida:
fuente
Una solución GUI se acerca mucho a su pregunta:
No puede enumerar los archivos vinculados reales de "ls" porque, como han señalado los comentaristas anteriores, los "nombres" de los archivos son meros alias de los mismos datos. Sin embargo, en realidad hay una herramienta GUI que se acerca mucho a lo que desea, que es mostrar una lista de rutas de nombres de archivos que apuntan a los mismos datos (como enlaces duros) en Linux, se llama FSLint. La opción que desea está en "Choques de nombres" -> deseleccione "casilla de verificación $ RUTA" en Buscar (XX) -> y seleccione "Alias" en el cuadro desplegable después de "para ..." hacia la parte superior central.
FSLint está muy poco documentado, pero descubrí que asegurándose de que el árbol de directorios limitado en "Ruta de búsqueda" con la casilla de verificación seleccionada para "¿Recurrir?" y las opciones antes mencionadas, una lista de datos vinculados con rutas y nombres que "apuntan" a los mismos datos se producen después de las búsquedas del programa.
fuente
Puede configurar
ls
para resaltar los enlaces duros usando un 'alias', pero como se indicó anteriormente, no hay forma de mostrar la 'fuente' del enlace duro, por lo que anexo.hardlink
ayuda con eso.Agregue lo siguiente en algún lugar de su
.bashrc
fuente