mv a file to /dev/null breaks dev/null
Solution 1
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
.
Solution 2
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
.
Solution 3
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
Gregg Leventhal
Updated on September 18, 2022Comments
-
Gregg Leventhal over 1 year
If I do:
touch file; mv file /dev/null
as root,/dev/null
disappears.ls -lad /dev/null
results in no such file or directory. This breaks applications which depend on/dev/null
like SSH and can be resolved by doingmknod /dev/null c 1 3; chmod 666 /dev/null
. Why does moving a regular file to this special file result in the disappearance of/dev/null
?To clarify, this was for testing purposes, and I understand how the
mv
command works. What I am curious about is whyls -la /dev/null
before replacing it with a regular file shows the expected output, but afterwards it shows that/dev/null
does not exist even though a file was allegedly created via the originalmv
command and the file command shows ASCII Text. I think this must be a combination of thels
command behavior in conjunction withdevfs
when a non special file replaces a character/special file. This is on Mac OS X, behaviors may vary on other OS's.-
Admin about 10 yearsDon't mess with
/dev/null
. -
Admin about 10 yearsso says @devnull
-
Admin about 10 yearsThe proper way to delete files is the
rm
command. -
Admin about 10 yearsI am not trying to delete anything, this was an experiment. The thing I am curious about is that replacing the file results in the file being missing when ls -la /dev/null is run. I am guessing this is due to the nature of devfs.
-
Admin about 10 years@Gregg, does a Mac use
devfs
? -
Admin about 10 yearsYes df -h Greggs-MacBook-Air1:~ gleventhal$ df -h /dev Filesystem Size Used Avail Capacity iused ifree %iused Mounted on devfs 191Ki 191Ki 0Bi 100% 660 0 100% /dev
-
Admin about 10 years@Gregg, can you also create normal files on the OSX
/dev
, egtouch /dev/testfile
. -
Admin about 10 yearsJust to make sure it's not specific to
ls
, runfind /dev -n name null
to test whetherfind
can see it. I really doubt it will but may as well. -
Admin about 10 yearsOn a Mac, as root touch /dev/test results in operation not supported.
-
Admin about 10 yearsSeems like that is the root of your problem, OSX
devfs
is funny about normal files. Strange you didn't get an error frommv
though. How about this way:touch testfile; mv testfile /dev
? -
Admin about 10 yearstouch testfile; mv testfile /dev results in operation not supported too, so I am going to assume when you mv file /dev/null on a Mac you are "unlinking" /dev/null and then the mv fails, but this seems weird since mv is supposed to be atomic.
-
Admin about 10 years@GreggLeventhal So it was pointed out to me. I deleted my comment, but too late to stop you answering. :-) In the interest of reducing clutter, if you delete your comment, I'll delete mine. Just ping me on chat, and sorry about the noise.
-
Admin about 10 years@Gregg,
mv
can only be atomic on the same filesystem. -
Admin about 10 yearsMaybe this @DE_WHITEOUT flag?
-
-
Gregg Leventhal about 10 yearsBut I am saying /dev/null was showing as missing when running an ls -lad /dev/null. This must be something specific to the devfs, that it what I wanted to know about.
-
Gregg Leventhal about 10 yearsIf I mv file /dev/null then /dev/null should contain what file contained but still exist. I want to know why this caused /dev/null to not be found in an ls.
-
Gregg Leventhal about 10 yearsSee my comments to terdon.
-
Gregg Leventhal about 10 yearsUnderstood, the -d was unneeded, that is just a bad habit however the file should still show up in the ls output, it should not show as nonexistent.
-
terdon about 10 years@GreggLeventhal yes, it must be an OSX or BSD thing (please edit your Q and specify your OS). On my Linux I can still see
/dev/null
, it's just become the file I moved. -
slm about 10 years@Graeme - welcome to 3K, nice job!
-
Gregg Leventhal about 10 yearsI am giving this best answer right now for providing source code and acknowledging this as a bug, which is what I was driving at.