如果我这样做:touch file; mv file /dev/null作为根,/dev/null消失。 ls -lad /dev/null结果没有这样的文件或目录。这会破坏依赖于/dev/nullSSH 的应用程序,并且可以通过执行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)