On Sun, Feb 12, 2017 at 4:09 AM, Steve D'Aprano <steve+pyt...@pearwood.info> wrote: > On Fri, 10 Feb 2017 12:07 am, eryk sun wrote: > >> On Thu, Feb 9, 2017 at 11:46 AM, Steve D'Aprano >> <steve+pyt...@pearwood.info> wrote: >>> >>> So to summarise, os.rename(source, destination): >>> >>> - is atomic on POSIX systems, if source and destination are both on the >>> same file system; >>> - may not be atomic on Windows? >>> - may over-write an existing destination on POSIX systems, but not on >>> Windows; >>> - and it doesn't work across file systems. >> >> On Windows in 2.7 and prior to 3.3, os.rename will silently copy and >> delete when the destination isn't on the same volume. > > Will the copy overwrite an existing file?
2.7/3.2 calls MoveFile. This is effectively the same as (but not necessarily implemented by) MoveFileEx with the flag MOVEFILE_COPY_ALLOWED. It will not replace an existing file whether or not the target is on the same volume. For a cross-volume move, it's effectively a CopyFile followed by DeleteFile. If deleting the source file fails, it tries to reset the file attributes and retries the delete. > On Windows, how would you implement a file rename (potentially across file > system boundaries) which will not overwrite existing files? Just by calling > os.rename()? I'd prefer to always call shutil.move on Windows. In 2.7 the os.rename call in shutil.move will copy and delete for a cross-volume move of a file, but fail for a directory. In the latter case shutil.move falls back on shutil.copytree and shutil.rmtree. The OS won't allow replacing an existing file with a directory, so that's not a problem. In 3.3+ os.rename doesn't move files across volumes on any platform -- I think. In this case the default copy2 function used by shutil.move is a problem for everyone. Ideally we want "x" mode instead of "w" mode for creating the destination file. It raises a FileExistsError. 3.5+ allows using a custom copy function to implement this. -- https://mail.python.org/mailman/listinfo/python-list