Quelle est la difference entre 'rm' et 'unlink'?

55

En supposant que vous sachiez que la cible est un lien symbolique et non un fichier, existe-t-il une différence entre utiliser rmet unlinksupprimer le lien?

IQAndreas
la source
3
Ceci est assez bien couvert sur ServerFault: serverfault.com/questions/38816/…
slm
@ slm ♦ Les réponses correspondent à cette question, mais cette question est différente: "En supposant que vous sachiez que la cible est un lien symbolique et non un fichier".
Stéphane Gourichon
Ne semble pas que vous ayez accepté une réponse ici @IQAndreas. S'il vous plaît, faites-le s'ils vous ont aidé.
Gray

Réponses:

56

Chaque fois que vous avez ce type de questions, il est préférable de concevoir un petit test pour voir ce qui se passe réellement. Pour cela, vous pouvez utiliser strace.

dissocier

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

rm

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

Lorsque vous examinez les 2 fichiers journaux résultants, vous pouvez "voir" ce que fait réellement chaque appel.

Panne

Avec unlinkl'appel de l' unlink()appel système:

....
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)                           = ?
....

Avec rmc'est un chemin légèrement différent:

....
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 +++
...

Les appels système unlink()et unlinkat()sont essentiellement les mêmes, à l'exception des différences décrites dans cette page de manuel: http://linux.die.net/man/2/unlinkat .

extrait

L'appel système unlinkat () fonctionne exactement de la même manière que unlink (2) ou rmdir (2) (selon que les options incluent ou non l'indicateur AT_REMOVEDIR), à l'exception des différences décrites dans cette page de manuel.

Si le nom de chemin indiqué dans chemin est relatif, il est interprété par rapport au répertoire référencé par le descripteur de fichier dirfd (plutôt que par rapport au répertoire de travail actuel du processus appelant, comme le font par unlink (2) et rmdir (2). ) pour un chemin relatif).

Si le nom de chemin indiqué dans chemin est nom relatif et que dirfd est la valeur spéciale AT_FDCWD, le chemin est interprété par rapport au répertoire de travail actuel du processus appelant (comme unlink (2) et rmdir (2)).

Si le chemin indiqué dans chemin est absolu, alors dirfd est ignoré.

slm
la source
1
Étant donné que c'est donner AT_FDCWD, il n'y a effectivement aucune différence entre unlinket unlinkat.
Barmar
6
Cela me fait plaisir de lire cette réponse parce que je viens "d'apprendre à pêcher" de manière puissante et flexible lorsque je prends souvent un poisson ou parfois "d'apprendre à pêcher" de manière basique sur SO :-)
sage
22

POSIX spécifie que l' unlinkutilitaire appelle la unlinkfonction de bibliothèque C et rien d'autre. Cela ne prend aucune option. Si vous transmettez un nom de chemin valide à quelque chose qui n'est pas un répertoire et si vous disposez d'autorisations en écriture sur le répertoire où cet objet réside, vous unlinkle supprimerez.

rmest une commande Unix traditionnelle qui a un peu d'autres fonctionnalités et qui n'est pas vraiment un sur-ensemble unlink(voir ci-dessous).

Tout d'abord, rmeffectue des contrôles de sécurité. Si vous essayez rmun objet pour lequel vous ne possédez pas d’autorisation en écriture (qui n’a aucune incidence sur votre capacité à le supprimer: les autorisations directes le sont!) rmRefuse néanmoins sauf si -fest spécifié. rmse plaint normalement si le fichier n'existe pas, comme c'est le cas unlink; cependant avec -f, rmne se plaint pas. Ceci est souvent exploité dans Makefiles ( clean: @rm -f $(OBJS) ...), donc make cleann'échoue pas lorsqu'il n'y a rien à supprimer.

Deuxièmement, rma la -ipossibilité de confirmer de manière interactive la suppression.

Troisièmement, il rmfaut -rsupprimer récursivement un répertoire, ce qui unlinkn’est pas obligatoire, car la fonction de bibliothèque C ne le fait pas.

L' unlinkutilitaire n'est pas vraiment un dépouillé rm. Il exécute un sous-ensemble de ce qui rmfonctionne, mais il a une sémantique qui est une combinaison de rm with -f et rm without -f .

Supposons que vous souhaitiez simplement supprimer un fichier normal, quelles que soient ses propres autorisations. De plus, supposez que vous souhaitiez que la commande échoue si le fichier n'existe pas ou pour toute autre raison. Ni rm fileni rm -f filerépond aux exigences. rm filerefusera si le fichier n'est pas accessible en écriture. Mais rm -f filenéglige de se plaindre si le fichier est manquant. unlink fileFait le travail.

unlinka probablement été introduit parce qu’il rmest trop intelligent: parfois, vous voulez juste la unlinksémantique Unix pure : "veuillez faire en sorte que cette entrée de répertoire disparaisse si les autorisations de répertoire le permettent" .

Kaz
la source
2
C'est la réponse la plus claire ici. Il donne en fait le cas d'utilisation pour unlinkplutôt que de simplement décrire les différences.
Wildcard
19

Avec un seul fichier, rm et unlink effectuent la même tâche, supprimez le fichier. Comme défini POSIX, rmet à la unlinkfois appel à unlink () appel système.

Dans GNU rm, il appelle l’ appel système unlinkat () , ce qui équivaut à la fonction unlink()ou à la fonction rmdir () , sauf dans le cas où chemin spécifie un chemin relatif.

Remarque

Sur certains systèmes, unlinkpeut également supprimer un répertoire. Au moins dans le système GNU, unlinkne peut jamais supprimer le nom d’un répertoire.

cuonglm
la source