舒蒂尔。快走当新名称包含冒号(和扩展名)时删除windows上的文件

2024-05-20 00:01:32 发布

您现在位置:Python中文网/ 问答频道 /正文

尝试:

import os, shutil

wd = os.path.abspath(os.path.curdir)
newfile = os.path.join(wd, 'testfile')
print str(newfile)
with open(newfile, 'w') as f: f.write('Hello bugs')
shutil.move(newfile, os.path.join(wd, 'testfile:.txt')) # note the :

现在检查目录-新文件被删除并且没有创建其他文件-进程结束,退出代码为0。在

如果您发出:

^{pr2}$

它吹出:

Traceback (most recent call last):
      File "C:/Users/MrD/.PyCharm40/config/scratches/scratch_3", line 9, in <module>
        shutil.move(newfile, os.path.join(wd, 'testfile:'))
      File "C:\_\Python27\lib\shutil.py", line 302, in move
        copy2(src, real_dst)
      File "C:\_\Python27\lib\shutil.py", line 130, in copy2
        copyfile(src, dst)
      File "C:\_\Python27\lib\shutil.py", line 83, in copyfile
        with open(dst, 'wb') as fdst:
    IOError: [Errno 22] invalid mode ('wb') or filename: 'C:\\Users\\MrD\\.PyCharm40\\config\\scratches\\testfile:'

它应该如此。在

是虫子吗?在

上下文:我在测试我的代码的行为时给出了非法的文件名(:在windows文件名中是非法的)当我惊讶于我的程序删除了原始文件(坏!)并创建了一个具有原始文件属性的零大小文件(在我的例子中文件创建的,只是空的)和文件名,文件名给了:-soo一个像textfile:.jpg的文件名给了我一个零字节textfile。这需要大量的调试-这是Python27\lib中的一个小家伙\舒蒂尔.pycopyfile()(在上面吹而没有吹的线):

enter image description here

我不知道为什么在我的例子中,文件是在运行脚本时创建的


Tags: 文件pathinmoveos文件名libline
1条回答
网友
1楼 · 发布于 2024-05-20 00:01:32

这不是Python的shutilos模块中的bug,它只是Windows中的一个奇怪之处。peterwood的link在评论中讨论了“高级数据流”一种Windows文件系统机制,它将包含元数据的隐藏文件附加到常规的可见文件中。关键字是一个附加的关键字;如果所附加的文件被删除,则删除隐藏的文件。在

似乎用冒号分隔常规文件和隐藏文件的路径。例如,如果在命令行中写入:

> notepad foo

然后关闭记事本,然后写入

^{pr2}$

记事本将打开隐藏的文件。继续写一些东西,保存,然后关闭。输入> dir命令行将只显示foo.txt,而不是{}。但如果你写信

> notepad foo.txt:bar.txt

您刚刚编辑的文件将出现,您的更改将保持不变。在

那么你的Python代码发生了什么呢?{a2的文档中说:

src is copied (using shutil.copy2()) to dst and then removed.

因此,当您将testfile移动到testfile:.txt时,Python首先将testfile复制到隐藏的testfile:.txt。但随后它会移除隐藏的。因此,在您看来,原始文件已被删除,而没有创建新文件。在

下面的代码片段可能会使这一点更清楚(我将其保存为demo.py,并且我在同一个,其他明智的空目录中运行它):

import os, shutil


with open('test', 'w') as f:
    f.write('Hello bugs')

shutil.copy2('test', 'test:foo.txt')

with open('test:foo.txt') as f:
    print(f.read())

print 'test: exists? ', os.path.exists('test')
print 'test:foo.txt exists? ', os.path.exists('test:foo.txt')
print os.listdir('.')

print('removing...')
os.remove('test')

print 'test: exists? ', os.path.exists('test')
print 'test:foo.txt exists? ', os.path.exists('test:foo.txt')
print os.listdir('.')

打印:

Hello bugs
test exists? True
test:foo.txt exists? True
['demo.py', 'test']
removing...
test: exists? False
test:foo.txt exists? False
['demo.py']

这表明我们可以创建一个普通文件,对其进行写入,然后将该普通文件复制到其隐藏流中,打开并读取它,结果如预期的那样。然后我们看到os.path.exists表示test和它的隐藏附件{}都存在,即使{}只显示{}。然后我们删除test,我们发现{}也不再存在。在

最后,不能创建没有名称的隐藏数据流,因此test:是无效路径。在这种情况下,Python正确地抛出了一个异常。在

因此,Python代码实际上在Windows下正常工作,“替代数据流”只是一个鲜为人知的“特性”,这种行为令人惊讶。在

相关问题 更多 >