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
而不仅仅是描述差异。