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
signature.asc
Description: OpenPGP digital signature
