mv a file to /dev/null breaks dev/null
Looking at the source code for 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);
}
In the first pass through the while loop, open(to, O_CREAT | O_EXCL | O_TRUNC | O_WRONLY, 0)
will fail with EEXIST. Then /dev/null
will be unlinked, and the loop repeated.
But as you pointed out in your comment, regular files can't be created in /dev
, so on the next pass through the loop, open(to, O_CREAT | O_EXCL | O_TRUNC | O_WRONLY, 0)
is still going to fail.
I'd file a bug report with Apple. The mv
source code is mostly unchanged from the FreeBSD version, but because OSX's devfs has that non-POSIX behavior with regular files, Apple should fix their mv
.
Moving a file to the location of an already existing file replaces the existing file. In this case the /dev/null
device file is replaced, just as any normal file would be. To avoid this use the -i
(interactive, warns before overwriting) or -n
(no clober) option for mv
.
/dev/null
only performs its special function as a bit-bucket then the device is opened as is. Eg, when the >
shell operator is used, the file is opened then truncated (not removed an replaced, which may be what you expected). As mentioned by casey, the correct way to remove a file is with rm
or even with unlink
.
Umm, because you overwrite the special file with normal one? What did you expect to happen? dev/null
is not a directory, it is a file pointing to a null
device. When you mv
something to it, you delete the original and replace it with whatever you moved:
$ file /dev/null
/dev/null: character special
$ sudo mv file /dev/null
$ file /dev/null
/dev/null: ASCII text