Rename file without overwriting existing files

eryk sun eryksun at gmail.com
Thu Feb 9 08:07:33 EST 2017


On Thu, Feb 9, 2017 at 11:46 AM, Steve D'Aprano
<steve+python at 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. It may even
silently leave the original file in place in some cases -- e.g. when
the file is read-only and the user isn't allowed to modify the file
attributes.

If the destination is on the same volume, renaming should be atomic
via the system calls NtOpenFile and NtSetInformationFile. Ultimately
it depends on the file system implementation of
IRP_MJ_SET_INFORMATION, FileRenameInformation [1].

> The link/unlink trick:
> - avoids over-writing existing files on POSIX systems at least;
> - but maybe not Windows?

This works for renaming files on Windows as long as the file system
supports hard links (e.g. NTFS). It's not documented on MSDN, but
WinAPI CreateHardLink is implemented by calling NtSetInformationFile
to set the FileLinkInformation, with ReplaceIfExists set to FALSE, so
it fails if the destination exists. Note that this does not allow
renaming directories. See the note for FileLinkInformation [1]; NTFS
doesn't allow directory hard links. But why bother with this 'trick'
on Windows?

[1]: https://msdn.microsoft.com/en-us/library/ff549366



More information about the Python-list mailing list