“ rm”和“ unlink”有什么区别?


55

假设您知道目标是符号链接而不是文件,那么使用rmunlink删除链接之间有什么区别吗?


3
这是相当不错覆盖上ServerFault:serverfault.com/questions/38816/...
SLM

@ slm♦答案与该问题相对应,但是此问题有所不同,它说:“假设目标对象是符号链接而不是文件”。
斯特凡纳·古里科

您似乎在@IQAndreas此处未接受答案。如果他们帮助您,请这样做。
灰色

Answers:


56

每当您遇到这些类型的问题时,最好进行一些测试以查看实际发生的情况。为此,您可以使用strace

取消连结

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

R M

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

查看2个结果日志文件时,您可以“查看”每个调用的实际操作。

分解

通过unlink它调用unlink()系统调用:

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

随着rm这是一个稍微不同的路径:

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

系统调用unlink()unlinkat()基本上相同,除了本手册页中描述的差异:http : //linux.die.net/man/2/unlinkat

摘抄

除了本手册页中所述的区别之外,unlinkat()系统调用的操作方式与unlink(2)或rmdir(2)完全相同(取决于标志是否包括AT_REMOVEDIR标志)。

如果在路径名中给定的路径名​​是相对的,则它相对于文件描述符dirfd所引用的目录进行解释(而不是相对于调用进程的当前工作目录,如unlink(2)和rmdir(2 )作为相对路径名)。

如果在路径名中给定的路径名​​是相对的并且dirfd是特殊值AT_FDCWD,则将相对于调用进程的当前工作目录(例如unlink(2)和rmdir(2))解释路径名。

如果在路径名中给定的路径名​​是绝对的,则dirfd被忽略。


1
由于提供AT_FDCWD,因此unlink和之间实际上没有区别unlinkat
Barmar 2014年

6
这让我很高兴阅读这个答案,因为我只是经常以一种有力的,灵活的方式“学习钓鱼”,而当我经常得到一条鱼时,或者有时我以一种基本的方式“学习钓鱼”于SO :-)
Sage

20

POSIX指定该unlink实用程序调用C库unlink函数,而不执行其他任何操作。它没有选择。如果将有效的路径名传递给不是目录的内容,并且对该对象所在的目录具有写权限,unlink则将其删除。

rm是传统的Unix命令,具有一些其他功能,并且不是的超集unlink(请参见下文)。

首先,rm进行安全检查。但是,如果尝试对rm没有写权限的对象(与删除它的能力无关:直接权限是!)rm-f则除非指定,否则拒绝。 rm通常会抱怨文件是否不存在unlink;但是用-frm不抱怨。这通常在Makefiles(clean: @rm -f $(OBJS) ...)中被利用,因此make clean在没有要删除的内容时不会失败。

其次,rm可以-i选择以交互方式确认删除。

第三,rm必须-r递归删除目录,这是unlink不需要执行的操作,因为C库函数不会执行该操作。

unlink实用程序并非完全精简rm它执行的是什么的一个子集rm的做法,但它的语义是组合rm -f和rm 没有 -f

假设您只想删除常规文件,而不管其自身的权限是什么。此外,假设您希望该命令在文件不存在或其他任何原因时失败。 既不rm file也不rm -f file符合要求。rm file如果文件不可写,将拒绝。但是rm -f file如果文件丢失,将忽略抱怨。unlink file做这份工作。

unlink之所以引入,rm是因为它太聪明了:有时您只想要纯Unix unlink语义:“如果目录权限允许,请使该目录条目消失”


2
这是这里最明确的答案。实际上,它提供了用例unlink而不仅仅是描述差异。
通配符'18

19

对于单个文件,rmunlink执行相同的任务,请删除该文件。如POSIX所定义,rm并且unlink都调用unlink()系统调用。

在GNU中rm,它调用unlinkat()系统调用,这等效于unlink()rmdir()函数,但path指定相对路径的情况除外。

注意

在某些系统上,unlink也可以删除目录。至少在GNU系统中,unlink永远不能删除目录名称。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.