shutil.move 在新名称包含冒号(和扩展名)时删除 windows 上的文件
shutil.move deletes the file on windows when new name contains a colon (and an extension)
尝试:
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。
如果您发出:
shutil.move(newfile, os.path.join(wd, 'testfile:')) # note no extension
吹的是:
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\shutil.py copyfile()
中的小动物(上面吹过但没有吹过的线):
我不知道为什么在我的情况下创建了文件,而 运行 脚本编号
这不是 Python 的 shutil
或 os
模块中的错误,它只是 Windows 中的一个怪异之处。 Peter Wood 的 在评论中讨论了 "Advanced Data Streams" —— 一种 Windows 文件系统机制,它将包含元数据的隐藏文件附加到常规的可见文件。附上一个关键字;删除附加文件后,隐藏文件也会被删除。
好像用冒号来分隔普通文件和隐藏文件的路径。例如,如果您在命令行中写入:
> notepad foo
然后关闭记事本,写入
> notepad foo.txt:bar
记事本将打开隐藏文件。继续在里面写点东西,保存,然后关闭。输入 > dir
,命令行将只显示 foo.txt
,而不显示 foo.txt:bar.txt
。但是果然,如果你写
> notepad foo.txt:bar.txt
您刚刚编辑的文件将出现,您的更改将完好无损。
那么您的 Python 代码发生了什么? shutil.move
的文档说:
src
is copied (using shutil.copy2()
) to dst
and then removed.
所以当你将testfile
移动到testfile:.txt
时,Python首先将testfile
复制到隐藏testfile:.txt
.但随后它 删除了 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:foo.txt
都存在,即使 os.listdir
只显示 test
。然后我们删除 test
,我们看到 test:foo.txt
也不再存在。
最后,您不能创建没有名称的隐藏数据流,因此 test:
是无效路径。 Python 在这种情况下正确抛出异常。
所以 Python 代码实际上在 Windows 下正常运行 -- "Alternate Data Streams" 只是一个鲜为人知的 "feature",这种行为令人惊讶。
尝试:
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。
如果您发出:
shutil.move(newfile, os.path.join(wd, 'testfile:')) # note no extension
吹的是:
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\shutil.py copyfile()
中的小动物(上面吹过但没有吹过的线):
我不知道为什么在我的情况下创建了文件,而 运行 脚本编号
这不是 Python 的 shutil
或 os
模块中的错误,它只是 Windows 中的一个怪异之处。 Peter Wood 的
好像用冒号来分隔普通文件和隐藏文件的路径。例如,如果您在命令行中写入:
> notepad foo
然后关闭记事本,写入
> notepad foo.txt:bar
记事本将打开隐藏文件。继续在里面写点东西,保存,然后关闭。输入 > dir
,命令行将只显示 foo.txt
,而不显示 foo.txt:bar.txt
。但是果然,如果你写
> notepad foo.txt:bar.txt
您刚刚编辑的文件将出现,您的更改将完好无损。
那么您的 Python 代码发生了什么? shutil.move
的文档说:
src
is copied (usingshutil.copy2()
) todst
and then removed.
所以当你将testfile
移动到testfile:.txt
时,Python首先将testfile
复制到隐藏testfile:.txt
.但随后它 删除了 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:foo.txt
都存在,即使 os.listdir
只显示 test
。然后我们删除 test
,我们看到 test:foo.txt
也不再存在。
最后,您不能创建没有名称的隐藏数据流,因此 test:
是无效路径。 Python 在这种情况下正确抛出异常。
所以 Python 代码实际上在 Windows 下正常运行 -- "Alternate Data Streams" 只是一个鲜为人知的 "feature",这种行为令人惊讶。