coreutils
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: mv -n with error code om failure


From: Eric Blake
Subject: Re: mv -n with error code om failure
Date: Tue, 21 May 2013 14:29:01 -0600
User-agent: Mozilla/5.0 (X11; Linux x86_64; rv:17.0) Gecko/20130514 Thunderbird/17.0.6

On 05/21/2013 01:56 PM, Edwin Klein Mentink wrote:
> I'm wanting to script file rename actions. But i never want to overwrite 
> already existing files.
> 
> There is the "-n" flag, but this returns 0 if the destination file does exist.
> If this is not a bug i like a "-N" flag which return a number on a failed 
> rename action.

mv -n is not specified by POSIX, but since other implementations support
it, it would be inconsiderate of us to have different semantics than
what other implementations have.  For example, on FreeBSD,

$ which mv
/bin/mv
$ touch a b
$ mv -n a b
$ echo $?
0
$ ls ?
a     b

which means that we are not alone to return success even when doing
nothing because -n detected an existing destination.  And even if we
were the only implementation to offer -n, changing exit status from
success to failure may break existing scripts.  So you are correct that
if we do anything, it would have to be via adding a new option.

However, adding a new short option is not a task to be taken lightly;
you may have better luck writing a patch that adds a long option to
return failure on any attempt to move atop an existing file, and only if
it seems to be frequently used, then promote it to a short option.

Additionally, we are reluctant to add new options for functionality that
already exists using other tools.  Does rsync already have a mode that
does what you want?  Can you use 'mv --update --verbose' or 'mv
--no-clobber --verbose' and parse the verbose output as a way to detect
whether a move was skipped because of an existing destination?

Finally, do you realize that there is fundamental a TOCTTOU race in
providing no-clobber semantics when mv operates on a local file system?
 When using 'mv' across file system boundaries (which is really a case
of cp then rm - and inherently non-efficient), the copy can use O_EXCL
on the destination and fail gracefully if the destination is present.
But when using 'mv' on a single file system, we are limited to the
rename(2) syscall (if we want to be efficient), but the rename(2)
syscall has no options to prevent overwriting an existing destination,
so we have to call lstat(2) first; but now there is a race between the
stat and the rename.  Maybe we could make the local file system behave
like the remote file system, if there was a way to force the
non-efficient copy algorithm instead of the fast rename algorithm, but
do you really want to code in a speed penalty just for race avoidance?
And if you _don't_ care about the race, then why not just do the stat
yourself prior to calling mv?  It's not that much harder to write your
script to do 'test -e "$dest"' and fail if the destination already
exists, rather than even trying the mv; and certainly something you can
use now rather than waiting a few years for a patch to be accepted into
coreutils and finally percolated into the machines you typically use.

-- 
Eric Blake   eblake redhat com    +1-919-301-3266
Libvirt virtualization library http://libvirt.org

Attachment: signature.asc
Description: OpenPGP digital signature


reply via email to

[Prev in Thread] Current Thread [Next in Thread]