我需要将脚本中的文件从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能够从本地剪切和粘贴到远程就好了。
加上..令我感到困惑的是,有些文件被移动了..
答案 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是留给读者的练习