What's the reason behind having -n option for mv command?

Sorry for a question that may seem dumb but learning UNIX basics I still can not grasp benefits of using

mv -n source file target file

I can understand the need for

 cp -n source file target file

when you get a copy with contents untouched but the former baffles me.
I know that this about preventing from overwriting a target file with contents of a source file (not in opposite order, right?) but why rename at all if you don't want to annihilate the target file? What's the point?

Would be glad to feel enlightened on the subject.

Did you think of moving to a different directory?

According to the man page of OS X i found in the net "-n" prevents the mv command to overwrite already existing files. That means: if you have files A, B and C and you do a

mv A D

you will end up with three files again, B, C and D (the former A). Whereas, when you issue:

mv A B

you will end up with only two files: B (the former A) and C. The original B will be wiped out. This may sometimes be the desired result, but sometimes it may not. To guard against accidentally wiping out a file you might want to keep is the reason "-n" exists.

I hope this helps.

bakunin

1 Like

Yeah, understand that. But my point and question was that if you pass -n option so that your command is designed as

mv -n A B

, then nothing happens. Both A and B are untouched so B IS NOT the former A. Right?

Not quite, see below.

Yes. This is what i'd expect.

I'd also expect some diagnostic message to be issued (i don't have OS X but i suppose it would be something along the lines of "Error: cannot ....") and the return-code to be non-zero. This is a common trait of UNIX-commands: whenenver they cannot do what is asked they will return a non-zero error code. Try the following:

ls -l /etc/hosts
echo RC is $?
ls -l /some/nonexisting/file
echo RC is $?

/etc/hosts is a file supposed to exist, so the return code should be zero, the second file does not exist, so the error code will be presumably 2 (if OS X-ls works the same way as my ls on AIX, the value might differ but it should be non-zero in any case).

I hope this helps.

bakunin

Below are the screenshots of my actions in OS X Terminal. As you see there're no alert messages. I have cat'ed both files beforehand so that their contents became evident. If I pass -n option then nothing happens - both are kept in the state they used to prior running the command (as evidenced in the portion of their directory listing I invoked through ls -lahG command).

And what is "overwrite2 not overwritten" (which i would guess is printed to stderr)?

It's an informational message in verbose mode (-v option) reporting on shell's activity when executing (or failing to execute) commands. Overwrite.txt and overwrite2.txt are the test files I created for learning purpose.

Two things: first, what you called an "informational message" i did call a "diagnostic message". In this regard i'd call the two expressions synonymous.

Second, and more important: no, the message is not "reporting on shell's activity" at all, because at this point the shell has no activity. When you issue the command:

mv A B

(regardless of the files involved and if it succeeds or not) what happens is: the shell first interprets the command line. If you happened to use a variable for a filename like this:

file="/some/file"
mv $file B

the shell would expand the variable to its content first.

Also, wildcards would be expanded. You didn't use any, but suppose your command would be

ls -l over*

then the shell would expand the "over*" to a list of filenames/directory names which start with "over". After such an expansion the command would look like this:

ls -l overwrite overwrite2

Also the PATH variable is used to locate "mv", which you entered without a path. Because perhaps "/usr/bin" is part of the PATH variable the shell calls "/usr/bin/mv" when you enter "mv". If "mv" would be a shell function then this would be executed instead. The same for an alias, etc.. So, after all these transformations, something like the following is in fact executed:

/usr/bin/mv A B

In fact, executed is only the binary: "/usr/bin/mv". The shell will pass the parameters you gave at the command line already parsed (that is: broken into pieces one argument each) to the executable ("/usr/bin/mv"). At this point, the shell passes over to the executable and this runs on its own. The shell does nothing.

Only when the executable ends, it sets a "return code" and the shell sets its special variable "$?" to this return code. This is why i suggested to execute the 4 commands in post #5: the return code (or error code, another synonym) is set anew after each execution of a binary so that "$?" always holds the return code of the last command.

All this means: the "...not overwritten" is not a message from the shell, but in fact a message from "mv" which tells you what is going on. You could also issue a echo $? directly after and find out what the error code is - it is perhaps non-zero when the file could not be overwritten because of the -n switch.

I hope this helps.

bakunin