从本地linux文件夹移动到使用cifs挂载的Windows共享

时间:2014-10-30 13:19:31

标签: python linux windows file-io share

我需要将脚本中的文件从ext4 hdd上的本地文件夹移动到一个文件夹,该文件夹的窗口共享安装如下: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)甚至subprocess.call(['mv', src,dst], Shell=True)subprocess.call(['mv', src,dst])

因为linux文件的所有权/权限而获取每个文件的错误以及我可以告诉它的错误..

e.g。当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)说:[Errno 18]无效的跨设备链接

编辑:pcmanfm能够从本地剪切和粘贴到远程就好了。

加上..令我感到困惑的是,有些文件被移动了..

1 个答案:

答案 0 :(得分:3)

os.rename无法跨文件系统移动文件,因为基础rename syscall不会允许它:

  

rename()在不同的挂载点上不起作用,即使它们相同   文件系统安装在两者上。

至于shutil.move失败的原因,答案也在于its documentation

  

如果目标位于当前文件系统上,则只需使用   改名。否则,将src(带有copy2())复制到dst然后删除   SRC。

然后让我check copy2

  

与copy()类似,但也复制了元数据 - 事实上,这是   只需复制()后跟copystat()

因此,copystat失败了 - 因为它无法在这样的安装上设置文件元数据。

由于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)

似乎正如预测的那样,我们需要做的就是将copy2替换为copy。我们可以通过复制源代码并重命名函数或仅通过

来实现
def move_without_copying_stat(src,dst):
    old= shutil.copy2
    shutil.copy2= shutil.copy
    shutil.move(src,dst)
    shutil.copy2= old

如果你今天感到幸运。理解the consequences of such是留给读者的练习