从本地linux文件夹移到安装有cifs的Windows共享

我需要将脚本中的文件从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 

如果你今天感觉幸运。 理解这样的后果是作为练习给读者的