Answers:
每当您遇到这些类型的问题时,最好进行一些测试以查看实际发生的情况。为此,您可以使用strace。
$ touch file1
$ strace -s 2000 -o unlink.log unlink file1
$ 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被忽略。
AT_FDCWD,因此unlink和之间实际上没有区别unlinkat。
POSIX指定该unlink实用程序调用C库unlink函数,而不执行其他任何操作。它没有选择。如果将有效的路径名传递给不是目录的内容,并且对该对象所在的目录具有写权限,unlink则将其删除。
rm是传统的Unix命令,具有一些其他功能,并且不是的超集unlink(请参见下文)。
首先,rm进行安全检查。但是,如果尝试对rm没有写权限的对象(与删除它的能力无关:直接权限是!)rm,-f则除非指定,否则拒绝。 rm通常会抱怨文件是否不存在unlink;但是用-f,rm不抱怨。这通常在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语义:“如果目录权限允许,请使该目录条目消失”。
unlink而不仅仅是描述差异。