如果我这样做:touch file; mv file /dev/null
作为根,/dev/null
消失。 ls -lad /dev/null
结果没有这样的文件或目录。这会破坏依赖于/dev/null
SSH 的应用程序,并且可以通过执行mknod /dev/null c 1 3; chmod 666 /dev/null
. 为什么将常规文件移动到这个特殊文件会导致/dev/null
?
澄清一下,这是出于测试目的,我了解该mv
命令的工作原理。我很好奇的是为什么ls -la /dev/null
在用常规文件替换它之前显示预期的输出,但之后它显示/dev/null
不存在,即使据称是通过原始mv
命令创建的文件并且文件命令显示 ASCII 文本。我认为这必须是ls
命令行为与devfs
非特殊文件替换字符/特殊文件时的组合。这是在 Mac OS X 上,行为在其他操作系统上可能会有所不同。
Mar*_*ick 16
查看 mv 的源代码,http : //www.opensource.apple.com/source/file_cmds/file_cmds-220.7/mv/mv.c:
/*
* If rename fails because we're trying to cross devices, and
* it's a regular file, do the copy internally; otherwise, use
* cp and rm.
*/
if (lstat(from, &sb)) {
warn("%s", from);
return (1);
}
return (S_ISREG(sb.st_mode) ?
fastcopy(from, to, &sb) : copy(from, to));
...
int
fastcopy(char *from, char *to, struct stat *sbp)
{
...
while ((to_fd =
open(to, O_CREAT | O_EXCL | O_TRUNC | O_WRONLY, 0)) < 0) {
if (errno == EEXIST && unlink(to) == 0)
continue;
warn("%s", to);
(void)close(from_fd);
return (1);
}
Run Code Online (Sandbox Code Playgroud)
在第一次通过 while 循环时,open(to, O_CREAT | O_EXCL | O_TRUNC | O_WRONLY, 0)
将失败并显示 EEXIST。然后/dev/null
将被取消链接,并重复循环。但是正如您在评论中指出的那样,无法在 中创建常规文件/dev
,因此在下一次通过循环时,open(to, O_CREAT | O_EXCL | O_TRUNC | O_WRONLY, 0)
仍然会失败。
我会向 Apple 提交错误报告。该mv
源代码主要来自FreeBSD版本不变,但由于OSX的devfs的有规则的文件,非POSIX行为,苹果应该解决他们的mv
。
Gra*_*eme 12
将文件移动到现有文件的位置会替换现有文件。在这种情况下,/dev/null
设备文件被替换,就像任何普通文件一样。为避免这种情况-i
,请-n
为mv
.
/dev/null
仅作为位桶执行其特殊功能,然后设备按原样打开。例如,当使用>
shell 运算符时,文件被打开然后被截断(不是删除和替换,这可能是您所期望的)。正如凯西所提到的,删除文件的正确方法是使用rm
或什至使用unlink
.
ter*_*don 10
嗯,因为你用普通文件覆盖了特殊文件?你期望会发生什么?dev/null
不是目录,而是指向null
设备的文件。当你mv
对它做某事时,你删除原来的并用你移动的任何东西替换它:
$ file /dev/null
/dev/null: character special
$ sudo mv file /dev/null
$ file /dev/null
/dev/null: ASCII text
Run Code Online (Sandbox Code Playgroud)