I was trying to overwrite an existing file with another file I created, with a
Python script, using os.rename
. Instead of doing what the tin says,
os.rename
failed with the rather intimidating message:
OSError: [Errno 18] Invalid cross-device link
WTF? DuckDuckGo to the rescue. I found a thread from the Python mail-list, which I'll reproduce below:
Scott Whitney wrote:
os.rename(oldName,newName) gives: OSError: [Errno 18] Invalid cross-device link
mv from the shell works fine. This is Python 2.2.3 from RedHat 9.0.
Any suggestions (other than os.system('mv %s %s')?)
catch exception and copy if error == errno.EXDEV. (this is what "mv" does, of course)
or use shutil.move:
>>> import shutil >>> help(shutil.move) Help on function move in module shutil: move(src, dst) Recursively move a file or directory to another location. If the destination is on our current filesystem, then simply use rename. Otherwise, copy src to the dst and then remove src. A lot more could be done here... A look at a mv.c shows a lot of the issues this implementation glosses over.
And a subsequent mail from that thread:
mv is a surprisingly complex program, while os.rename is a wrapper around rename(2) which is probably documented on your system to return EXDEV under these circumstanes.
os.xxx is generally a fairly thin wrapper around what your OS provides, and inherits all the "gotchas". For some activities, os.shutil provides something that is between os.xxx and os.system("xxx") in complexity and capability.
The (somewhat silly) moral of the story: the os
module might not be what you
want. Or, the os
module is a rather awkward way of learning about your OS's
system calls.