¿Cuál es la diferencia entre 'rm' y 'unlink'?

55

Suponiendo que sabe que el objetivo es un enlace simbólico y no un archivo, ¿hay alguna diferencia entre usar rmy unlinkeliminar el enlace?

IQAndreas
fuente
3
Esto está bastante bien cubierto en ServerFault: serverfault.com/questions/38816/…
slm
@ slm ♦ Las respuestas corresponden a esa pregunta, pero esta pregunta es diferente, dice: "Suponiendo que sabes que el objetivo es un enlace simbólico y no un archivo".
Stéphane Gourichon
No parece que hayas aceptado una respuesta aquí @IQAndreas. Hazlo si te ayudaron.
Gray

Respuestas:

56

Cada vez que tenga este tipo de preguntas, es mejor concebir una pequeña prueba para ver qué está sucediendo realmente. Para esto puedes usar strace.

desconectar

$ touch file1
$ strace -s 2000 -o unlink.log unlink file1

rm

$ touch file1
$ strace -s 2000 -o rm.log rm file1

Cuando observa los 2 archivos de registro resultantes, puede "ver" lo que cada llamada está haciendo realmente.

Descompostura

Con unlinkesto se invoca la unlink()llamada al sistema:

....
mmap(NULL, 106070960, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7f6d025cc000
close(3)                                = 0
unlink("file1")                         = 0
close(1)                                = 0
close(2)                                = 0
exit_group(0)                           = ?
....

Con rmes un camino ligeramente diferente:

....
ioctl(0, SNDCTL_TMR_TIMEBASE or SNDRV_TIMER_IOCTL_NEXT_DEVICE or TCGETS, {B38400 opost isig icanon echo ...}) = 0
newfstatat(AT_FDCWD, "file1", {st_mode=S_IFREG|0664, st_size=0, ...}, AT_SYMLINK_NOFOLLOW) = 0
geteuid()                               = 1000
newfstatat(AT_FDCWD, "file1", {st_mode=S_IFREG|0664, st_size=0, ...}, AT_SYMLINK_NOFOLLOW) = 0
faccessat(AT_FDCWD, "file1", W_OK)      = 0
unlinkat(AT_FDCWD, "file1", 0)          = 0
lseek(0, 0, SEEK_CUR)                   = -1 ESPIPE (Illegal seek)
close(0)                                = 0
close(1)                                = 0
close(2)                                = 0
exit_group(0)                           = ?
+++ exited with 0 +++
...

El sistema llama unlink()y unlinkat()es esencialmente el mismo, excepto por las diferencias descritas en esta página de manual: http://linux.die.net/man/2/unlinkat .

extracto

La llamada al sistema unlinkat () funciona exactamente de la misma manera que unlink (2) o rmdir (2) (dependiendo de si las banderas incluyen o no la bandera AT_REMOVEDIR) excepto por las diferencias descritas en esta página del manual.

Si el nombre de ruta proporcionado en pathname es relativo, entonces se interpreta en relación con el directorio al que hace referencia el descriptor de archivo dirfd (en lugar de en relación con el directorio de trabajo actual del proceso de llamada, como lo hacen unlink (2) y rmdir (2 ) para un nombre de ruta relativo).

Si el nombre de ruta proporcionado en pathname es relativo y dirfd es el valor especial AT_FDCWD, entonces pathname se interpreta en relación con el directorio de trabajo actual del proceso de llamada (como unlink (2) y rmdir (2)).

Si el nombre de ruta dado en pathname es absoluto, entonces dirfd se ignora.

slm
fuente
1
Dado que está dando AT_FDCWD, efectivamente no hay diferencia entre unlinky unlinkat.
Barmar
66
Me alegra leer esta respuesta porque acabo de "aprender a pescar" de una manera poderosa y flexible cuando a menudo obtengo un pez o, a veces, "aprendo a pescar" de manera básica en SO :-)
sage
22

POSIX especifica que la unlinkutilidad llama a la unlinkfunción de biblioteca C y nada más. No tiene opción. Si pasa un nombre de ruta válido a algo que no es un directorio, y si tiene permisos de escritura en el directorio donde vive ese objeto, unlinklo eliminará.

rmes un comando tradicional de Unix que tiene un poco de otra funcionalidad y no es un superconjunto unlink(ver más abajo).

En primer lugar, rmrealiza controles de seguridad. Si intenta rmun objeto para el que no tiene permisos de escritura (que son irrelevantes para su capacidad de eliminarlo: ¡los permisos directos sí lo son!), Sin rmembargo, se niega a menos que -fse especifique. rmnormalmente se queja si el archivo no existe, como lo hace unlink; sin embargo con -f, rmno se queja. Esto a menudo se explota en Makefiles ( clean: @rm -f $(OBJS) ...), por lo make cleanque no falla cuando no hay nada que eliminar.

En segundo lugar, rmtiene la -iopción de confirmar interactivamente la eliminación.

En tercer lugar, rmtiene -rpara eliminar recursivamente un directorio, que es algo que unlinkno es necesario hacer, ya que la función de biblioteca C no hace eso.

La unlinkutilidad no es exactamente una simplificada rm. Realiza un subconjunto de lo que rmhace, pero tiene una semántica que es una combinación de rm con -f y rm sin -f .

Suponga que desea eliminar un archivo normal independientemente de cuáles sean sus propios permisos. Además, suponga que desea que el comando falle si el archivo no existe o por cualquier otro motivo. Ni rm filetampoco rm -f filecumple con los requisitos. rm filese negará si el archivo no se puede escribir. Pero rm -f filedejará de quejarse si falta el archivo. unlink filehace el trabajo.

unlinkprobablemente se introdujo porque rmes demasiado inteligente: a veces solo desea la unlinksemántica pura de Unix : "haga que esta entrada del directorio desaparezca si los permisos del directorio lo permiten" .

Kaz
fuente
2
Esta es la respuesta más clara aquí. En realidad, da el caso de uso en unlinklugar de solo describir las diferencias.
Comodín el
19

Con un solo archivo, rm y unlink realizan la misma tarea, elimine el archivo. Como POSIX definió, rmy unlinkambos llaman a unlink () llamada al sistema.

En GNU rm, llama a la llamada al sistema unlinkat () , que es equivalente a la función unlink()o rmdir () , excepto en el caso en que la ruta especifica una ruta relativa.

Nota

En algunos sistemas, unlinktambién puede eliminar el directorio. Al menos en el sistema GNU, unlinknunca se puede eliminar el nombre de un directorio.

Cuonglm
fuente