
Eryk Sun added the comment: Having rename() in pathlib is fine as long as it links to the os docs. This probably needs a new issue, but I do see room for improvement in the latter. For Unix, the os.rename and os.replace docs should clarify that an empty destination directory can be replaced by another directory. For example: >>> os.mkdir('foo1') >>> os.mkdir('foo2') >>> os.rename('foo1', 'foo2') The specification of rename [1] states that "[i]f the *old* argument points to the pathname of a directory, the *new* argument shall not point to the pathname of a file that is not a directory". It further specifies that "[i]f *new* names an existing directory, it shall be required to be an empty directory". Windows, on the other hand, doesn't allow replacing a directory, even an empty one. The wording for os.rename and os.replace could be changed to something like: "[i]f dst is a directory, OSError will be raised, except not on Unix if src is a directory and dst is empty". Windows MoveFileEx calls NtSetInformationFile to set the FileRenameInformation [2]. The MSDN docs do not explicitly require that the operation is atomic, unlike POSIX rename. I think it's a reasonable expectation that a Windows filesystem should rename atomically, and that's probably the case. However, it should be clear that only Unix guarantees this, e.g. "[i]f successful, on Unix the renaming will be an atomic operation, as required by POSIX". MSDN claims that a rename will fail in the following cases: A file or directory can only be renamed within a volume. Even if ReplaceIfExists is set to TRUE, the rename operation will still fail if a file with the same name already exists and is a directory, a read-only file, or a currently executing file. A file cannot be renamed if it has any open handles, unless it is only open because of a batch opportunistic lock (oplock) and the batch oplock can be broken immediately. A file cannot be renamed if a file with the same name exists and has open handles (except in the batch-oplock case described earlier). A directory cannot be renamed if it or any of its subdirectories contains a file that has open handles (except in the batch-oplock case described earlier). For the third case, actually an open file can be renamed if delete/rename access is shared. For example: >>> with open('foo1', 'w') as f: f.write('foo1') ... 4 Open the file with shared delete access: >>> SHARE_ALL = 7 >>> _winapi.CreateFile('foo1', 0x80000000, SHARE_ALL, 0, 3, 0, 0) 224 and rename/replace succeeds: >>> os.replace('foo1', 'foo2') >>> open('foo2').read() 'foo1' Anyway, the os.replace docs could state in general that: "[o]n Windows, a PermissionError will be raised if dst is a read-only file, or if either src or dst is currently open, or if src is a directory with an open file". [1]: http://pubs.opengroup.org/onlinepubs/9699919799/functions/rename.html [2]: https://msdn.microsoft.com/en-us/library/ff540344 ---------- nosy: +eryksun _______________________________________ Python tracker <report@bugs.python.org> <https://bugs.python.org/issue27886> _______________________________________