¿Determinar si un archivo es un enlace duro o un enlace simbólico?


52

Estoy creando un script de shell que tomaría un nombre de archivo / ruta a un archivo y determinaría si el archivo es un enlace simbólico o un enlace duro.

Lo único es que no sé cómo ver si son un enlace duro. Creé 2 archivos, uno de enlace duro y otro de enlace simbólico, para usar como archivo de prueba. Pero, ¿cómo determinaría si un archivo es un enlace duro o simbólico dentro de un script de shell?

Además, ¿cómo encontraría la partición de destino de un enlace simbólico? Entonces, digamos que tengo un archivo que se vincula a una partición diferente, ¿cómo podría encontrar la ruta a ese archivo original?


16
¿Qué quieres decir con enlace duro? Todos los archivos son enlaces duros.
terdon

1
@terdon ln /foo/bar/ /foo/bar2hace un ln -s /foo/bar /foo/bar2enlace duro mientras hace un enlace simbólico, ¿a eso se refiere?
DisplayName

14
@DisplayName sí, pero todos los archivos son enlaces duros a su inodo. Así funcionan los sistemas de archivos Linux. En su ejemplo, bar2y barambos son enlaces duros, solo apuntan al mismo inodo.
terdon

10
@DisplayName sí, son enlaces duros a otros inodos . No hay contradicción aquí. Un archivo es un enlace a un inodo. Esa es la definición de un archivo. En su caso, tiene estos enlaces en diferentes lugares, pero eso no cambia la estructura de datos subyacente. Mi punto es que ambos bary bar2son igualmente importantes. Uno no es un enlace al otro, ambos son enlaces pero apuntan al mismo inodo.
terdon

3
@ Scott no, estoy diciendo que los archivos normales son enlaces duros y que los enlaces creados por lnno son diferentes a los archivos normales.
terdon

Respuestas:


42

La respuesta de Jim explica cómo probar un enlace simbólico: mediante el uso testde la -Lprueba.

Pero probar un "enlace duro" es, bueno, estrictamente hablando, no lo que quieres. Los enlaces duros funcionan debido a cómo Unix maneja los archivos: cada archivo está representado por un solo inodo. Luego, un solo inodo tiene cero o más nombres o entradas de directorio o, técnicamente, enlaces duros (lo que llama un "archivo").

Afortunadamente, el statcomando, donde esté disponible, puede decirle cuántos nombres tiene un inodo.

Entonces está buscando algo como esto (aquí asumiendo la implementación de GNU o busybox de stat):

if [ "$(stat -c %h -- "$file")" -gt 1 ]; then
    echo "File has more than one name."
fi

El -c '%h'bit le dice statque solo envíe el número de enlaces duros al inodo, es decir, el número de nombres que tiene el archivo. -gt 1luego comprueba si eso es más de 1.

Tenga en cuenta que los enlaces simbólicos, al igual que cualquier otro archivo, también se pueden vincular a varios directorios para que pueda tener varios enlaces duros a un enlace simbólico.


ok, para ser claros, puedo generar el número de enlaces duros que tiene el archivo usando el comando stat y si es mayor que 1, entonces tiene otro archivo vinculado en algún lugar de la partición.
k-Rocker

@ k-Rocker Sí. Luego tiene un segundo nombre en algún lugar de la partición.
derobert

1
En OS X o * BSD, es stat -f %l /path/to/file. También podría usarlo gstat -c %h /path/to/filesi tiene los GNU coreutils instalados sin sus nombres predeterminados (con Homebrew en OS X).
GDP2

29

Un ejemplo:

$ touch f1
$ ln f1 f2
$ ln f1 f3
$ ln -s f1 s1
$ ln -s f2 s2
$ ln -s ./././f3 s3
$ ln -s s3 s4
$ ln s4 s5
$ ls -li
total 0
10802124 -rw-r--r-- 3 stephane stephane 0 Nov 12 19:55 f1
10802124 -rw-r--r-- 3 stephane stephane 0 Nov 12 19:55 f2
10802124 -rw-r--r-- 3 stephane stephane 0 Nov 12 19:55 f3
10802345 lrwxrwxrwx 1 stephane stephane 2 Nov 12 19:56 s1 -> f1
10802346 lrwxrwxrwx 1 stephane stephane 2 Nov 12 19:56 s2 -> f2
10802347 lrwxrwxrwx 1 stephane stephane 8 Nov 12 19:56 s3 -> ./././f3
10802384 lrwxrwxrwx 2 stephane stephane 2 Nov 12 19:56 s4 -> s3
10802384 lrwxrwxrwx 2 stephane stephane 2 Nov 12 19:56 s5 -> s3

Las f1, f2y f3las entradas de directorio son el mismo archivo (el mismo nodo-i: 10802124, se dará cuenta el número de enlaces es 3). Son enlaces duros al mismo archivo regular .

s4y s5también son el mismo archivo (10802384). Son de tipo enlace simbólico , no regulares . Señalan un camino, aquí s3. Porque s4y s5son entradas del mismo directorio, esa ruta relativa s3apunta al mismo archivo (el que tiene inod 10802347) para ambos.

Si lo haces ls -Ll, es pedir obtener información del archivo después de resolver los enlaces simbólicos:

$ ls -lLi
total 0
10802124 -rw-r--r-- 3 stephane stephane 0 Nov 12 19:55 f1
10802124 -rw-r--r-- 3 stephane stephane 0 Nov 12 19:55 f2
10802124 -rw-r--r-- 3 stephane stephane 0 Nov 12 19:55 f3
10802124 -rw-r--r-- 3 stephane stephane 0 Nov 12 19:55 s1
10802124 -rw-r--r-- 3 stephane stephane 0 Nov 12 19:55 s2
10802124 -rw-r--r-- 3 stephane stephane 0 Nov 12 19:55 s3
10802124 -rw-r--r-- 3 stephane stephane 0 Nov 12 19:55 s4
10802124 -rw-r--r-- 3 stephane stephane 0 Nov 12 19:55 s5

Verá que todos se resuelven en el mismo archivo (10802124).

Puede verificar si un archivo es un enlace simbólico con [ -L file ]. Del mismo modo, puede probar si un archivo es un archivo normal [ -f file ], pero en ese caso, la verificación se realiza después de resolver los enlaces simbólicos.

los enlaces duros no son un tipo de archivo, solo son nombres diferentes para un archivo (de cualquier tipo).


19

Usando los operadores -hy -Ldel testcomando:

-h file 
true if file is a symbolic link

-L file 
true if file is a symbolic link

http://www.mkssoftware.com/docs/man1/test.1.asp

De acuerdo con este hilo SO , tienen el mismo comportamiento, pero -Lse prefiere.


ok genial, pero ¿qué pasa con los enlaces duros? Revisé la banda de rodadura, pero nada sobre enlaces duros. Si -L devuelve falso, ¿eso significa que es un enlace duro? o solo un archivo normal?
k-Rocker

1
Los enlaces duros comparten lo mismo inode. Además, los enlaces blandos muestran un lal comienzo de su ls -lsalida ... Creo que puede poner esas reglas juntas en un script, más la [[ -L file ]]prueba para ver si el archivo dado es blando o duro .
jimm-cl

ok, también, ¿cómo encontraría la partición de destino del enlace simbólico?
k-Rocker

3

Aquí hay muchas respuestas bastante correctas, pero no creo que nadie haya abordado realmente la percepción errónea original. La pregunta original es básicamente "cuando hago un enlace simbólico, es fácil identificarlo después. Pero no puedo entender cómo identificar un enlace duro". Y sí, las respuestas básicamente se reducen a "no se puede", y más o menos explican por qué, pero nadie parece haber reconocido que, realmente, ES confuso y extraño.

Si estás leyendo todo esto y has descubierto lo que está pasando, entonces eres bueno; No necesitas leer mi poquito. Si todavía estás confundido, sigue adelante.

La respuesta realmente muy corta es que un enlace duro no es realmente un enlace en absoluto, no en la forma en que lo es un enlace simbólico. Es una nueva entrada en la estructura del directorio que apunta al mismo grupo de bytes que la entrada original del directorio, y una vez que la ha creado, es tan 'real' y legítima como la primera. Cada archivo 'normal' en su disco tiene al menos un enlace duro; sin eso, no lo verías en ningunadirectorio, y no podría referirse a él o usarlo. Por lo tanto, si tiene un archivo Fred.txt y vincula con él Wilma.txt y Barney.txt, los tres nombres (y las entradas de directorio) se refieren al mismo archivo, y todos son igualmente válidos. No hay forma de que el sistema operativo indique que una de las entradas se creó cuando presionó "guardar" en su editor de texto, y las otras se hicieron con el comando "ln".

Sin embargo, el sistema operativo debe realizar un seguimiento de cuántas entradas diferentes apuntan al mismo archivo. Si elimina Wilma.txt, no sorprende que no libere espacio en su disco. Pero si elimina Fred.txt (el archivo 'original'), aún no liberará espacio en su unidad, porque los datos en la unidad que se conocían como Fred.txt también siguen siendo Barney.txt. Solo cuando elimine todas las entradas del directorio, el sistema operativo desasignará el espacio que ocupaban los datos.

Si Barney.txt hubiera sido un enlace simbólico, eliminar Fred.txt habría desasignado el espacio, y Barney.txt ahora sería un enlace roto. Además, si mueve o cambia el nombre de un archivo que tiene un enlace simbólico apuntando a él, romperá el enlace. Pero puede mover o cambiar el nombre de un archivo vinculado todo lo que quiera sin romper las otras entradas de directorio que apuntan a ese archivo / datos, porque todas ellas son entradas de directorio que se refieren al mismo bloque de datos en la unidad (mediante el uso de inodo # de esos datos).

[Dos años después, y eso último me confundió por un minuto, así que creo que lo aclararé. Si escribe "mv ./Wilma.txt ../elsewhere/Betty.txt" parece que está moviendo el archivo, pero de hecho, no lo está. Lo que realmente está haciendo es eliminar una línea de pedido de la lista de directorios de su directorio actual, la que dice "el nombre 'Wilma.txt' está asociado con los datos que se pueden encontrar usando el inodo ###### #, "y agregar una nueva línea de pedido a la lista de directorios del directorio ../ en otro lugar que dice" el nombre 'Betty.txt' está asociado con los datos que se pueden encontrar a través del inodo ####### ". Es por eso que puede 'mover' un archivo de 2 gigabytes tan rápido como un archivo de 2 kilobytes, siempre que los mueva a otra ubicación en la misma unidad.]

Debido a que el sistema operativo tiene que realizar un seguimiento de cuántas entradas de directorio diferentes apuntan a la misma porción de datos, puede saber si un archivo en particular ha sido vinculado, aunque no puede saber con certeza si la entrada de directorio que Lo que estás viendo es el 'original' o no. Una forma es el comando "ls", específicamente "ls -l" (esa es una L minúscula después del guión)

Para tomar prestado un ejemplo anterior ...

 -rw-r--r-- 3 stephane stephane 0 Nov 12 19:55 f1

La primera letra es un guión, por lo que no es un directorio u otra cosa exótica, es un archivo ordinario 'normal'. Pero si fuera realmente ordinario, ese número después de la parte rwx-ish sería "1", como en "hay una entrada de directorio que apunta a este bloque de datos". Pero es parte de una demostración de enlaces duros, por lo que dice "3".

Tenga en cuenta que esto posiblemente puede conducir a un comportamiento extraño y misterioso (si no ha entendido los enlaces duros, claro). Si abre Fred.txt en su editor de texto y realiza algunos cambios, ¿verá los mismos cambios en Wilma.txt y Barney.txt? Tal vez. Probablemente. Si su editor de texto guarda los cambios abriendo el archivo original y escribiendo los cambios en él, entonces sí, los tres nombres seguirán apuntando al mismo texto (recién cambiado). Pero si su editor de texto crea un nuevo archivo (Fred-new-temp.txt), escribe su versión modificada, luego elimina Fred.txt, luego cambia el nombre de Fred-new-temp.txt a Fred.txt, Wilma y Barney lo harán Todavía apunto a la versión original, no a la nueva versión modificada. Si no entiende los enlaces duros, esto podría volverlo un poco loco. :) [Bien, en realidad no conozco personalmente ningunaeditores de texto que harían lo de archivo nuevo / cambio de nombre, pero conozco muchos otros programas que hacen exactamente eso, así que manténgase alerta.]

Una nota final: una de las cosas que 'fsck' (verificación del sistema de archivos) comprueba es si hay bloques de datos en su disco que de alguna manera ya no son referenciados por ninguna entrada de directorio. A veces, algo sale mal y la única entrada de directorio que apunta a un inodo se elimina, pero el espacio de la unidad en sí no se marca como "disponible". Entonces, uno de los trabajos de fsck es hacer coincidir todo el espacio asignado con todas las entradas del directorio para asegurarse de que no haya archivos sin referencia. Si encuentra alguno, crea nuevas entradas de directorio y las coloca en "perdido + encontrado".


Me pregunto, ¿cuáles son esos "otros programas que hacen exactamente eso"?
phk

@phk No sé en qué está pensando específicamente, pero ese es un enfoque bastante común para realizar acciones que pueden llevar mucho tiempo y lo dejarán en un estado incierto si falla. Por ejemplo, si intenta descargar desde un servidor remoto y sabe que existe la posibilidad de que el servidor agote el tiempo de espera, un enfoque sería descargar todo el contenido en un archivo temporal. De esa manera, si algo sale mal con la descarga, todavía tiene el archivo original.
cwallenpoole

El único programa que conozco con certeza es FreeHand, porque si / cuando se bloquea durante un guardado, queda un archivo temporal, en lugar de un archivo original destrozado. Pero también he visto otros programas hacerlo; Simplemente no puedo darte ejemplos específicos en este momento.
Snarke

2

puedes usar readlink FILE; echo $?. Esto devuelve 1 cuando es un enlace duro y 0 cuando es un enlace simbólico.

Desde la página de manual: "Cuando se invoca como readlink, solo se imprime el objetivo del enlace simbólico. Si el argumento dado no es un enlace simbólico, readlink no imprimirá nada y saldrá con un error".

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.