我需要将脚本中的文件从ext4硬盘上的本地文件夹移动到一个文件夹,该文件夹是一个Windows共享挂载的: mount -t cifs -o username=username,password=password,rw,nounix,iocharset=utf8,file_mode=0777,dir_mode=0777 //192.168.1.120/storage /mnt/storage
我尝试使用os.rename(src,dst)
, shutil.move(src,dst)
甚至shutil.move(src,dst)
subprocess.call(['mv', src,dst], Shell=True)
或subprocess.call(['mv', src,dst])
获取每个文件的错误,从我可以告诉它,因为Linux文件所有权/权限..
例如,当mv /mnt/networkshare/file1.txt /tmp/file1.txt
是好的,但是
mv /tmp/file1.txt /mnt/networkshare/file1.txt
结果是
"mv: preserving times for /mnt/networkshare/file1.txt: Operation not permitted" "mv preserving permissions for /mnt/networkshare/file1.txt: Operation not permitted"
我认为os.rename(src,dst)
和shutil.move(src,dst)
会出现同样的问题,但它们并不那么健谈。
shutil.move(src,dst)
告诉我:[Errno 1]不允许操作:'/mnt/networkshare/file1.txt'
和os.rename(src,dst)
说:[错误18]无效的跨设备链接
编辑:pcmanfm是能够从本地剪切和粘贴到远程就好。
加上..什么让我感到困惑的是,一些文件被移动..
os.rename
不能跨文件系统移动文件,因为底层的rename
系统调用将不允许:
重命名()不能跨越不同的挂载点,即使两个挂载相同的文件系统。
至于为什么shutil.move
失败,答案也在于它的文档 :
如果目标位于当前文件系统上,那么只需使用重命名即可。 否则,复制src(copy2())到dst,然后删除src。
那我们来检查一下copy2
吧!
类似于copy(),但元数据也被复制 – 事实上,这只是copy(),后跟copystat()
所以,就是那个失败的copystat
– 因为它不能在这样的mount上设置文件元数据。
由于shutil
似乎没有复制元数据的方法来重命名,我们必须自己做。 我们来看看它的源代码:
In [3]: print inspect.getsource(shutil.move) def move(src, dst): """Recursively move a file or directory to another location. This is similar to the Unix "mv" command. If the destination is a directory or a symlink to a directory, the source is moved inside the directory. The destination path must not already exist. If the destination already exists but is not a directory, it may be overwritten depending on os.rename() semantics. If the destination is on our current filesystem, then rename() is used. Otherwise, src is copied to the destination and then removed. A lot more could be done here... A look at a mv.c shows a lot of the issues this implementation glosses over. """ real_dst = dst if os.path.isdir(dst): if _samefile(src, dst): # We might be on a case insensitive filesystem, # perform the rename anyway. os.rename(src, dst) return real_dst = os.path.join(dst, _basename(src)) if os.path.exists(real_dst): raise Error, "Destination path '%s' already exists" % real_dst try: os.rename(src, real_dst) except OSError: if os.path.isdir(src): if _destinsrc(src, dst): raise Error, "Cannot move a directory '%s' into itself '%s'." % (src, dst) copytree(src, real_dst, symlinks=True) rmtree(src) else: copy2(src, real_dst) os.unlink(src)
正如预测的那样,似乎我们所要做的就是copy
copy2
。 我们可以通过复制源代码并重命名函数或者简单地通过
def move_without_copying_stat(src,dst): old= shutil.copy2 shutil.copy2= shutil.copy shutil.move(src,dst) shutil.copy2= old
如果你今天感觉幸运。 理解这样的后果是作为练习给读者的