Python shutil.move: 奇怪的软链接

2 投票
1 回答
736 浏览
提问于 2025-04-17 04:46

我写了一个脚本,目的是把旧位置的每天的文件夹移动到新位置,结构大概是这样的:

/old/YYYY/MM/DD
/new/YYYY/MM/DD

另外,我在新位置创建了一个软链接,跟移动数据没关系(这是我犯的第一个错误):

/new/2011/09 -> /old/2011/09

我的脚本主要用了这个函数调用:

for d in os.listdir("/old/2011/09"):
    shutil.move(os.path.join("/old/2011/09/", d), os.path.join("/new/2011/09", d))

运行完脚本后,2011/09这个文件夹在两个地方都是空的。我在工作中也遇到过类似的情况,处理的是未归档的数据……这可真是个大问题。我想问的是,为什么shutil.move()没有给我报错,告诉我我想移动的日目录已经存在了呢? 09里面的每一天的文件夹应该是一样的,因为有软链接。

/new/2011/09/01 == /old/2011/09/01

shutil.move这个调用难道不会在调用shutil.copy2之前检查源和目标吗? 根据文档:“目标目录不能已经存在。”这是只在使用重命名的时候才这样吗?而且如果有影响的话,旧位置和新位置都是glusterfs。

shutil.move 文档

shutil.copy 文档

感谢你能提供的任何解释。

编辑/更新:我在python-list上提了个问题,问为什么会有这样的行为,并询问是否应该改变(邮件列表存档)。他们建议我提交一个bug报告。在做测试以提交bug的过程中,我发现这个问题在Python 2.7中已经修复了。你可以在move函数的源代码中看到差异: Python 2.6Python 2.7

现在这个函数仍然可以移动/重命名,但不会神奇地删除整个目录。

1 个回答

1

这段话主要讲的是在 shutil.move 这个函数里的两行代码:

        copytree(src, real_dst, symlinks=True)
        rmtree(src)

这里的 src='old' 表示你要移动的文件夹是叫做 old 的,而 real_dst='new/old' 表示你想把它移动到一个叫 new/old 的子文件夹里。这个 copytree 命令会把 old 复制到 new/old 这个地方,这个过程是没问题的,虽然可能不是你最开始想要的结果。

接着,rmtree 命令会把 old 这个文件夹删除。这就有点麻烦了,因为此时 new 变成了一个悬空的符号链接,也就是说它指向的地方已经不存在了。

撰写回答