这个问题并不直接与python绑定,但我需要在windows下的python32下进行工作。
从这个answer开始我假设使用shutil.rmtree()
真的慢(我需要每天删除超过3M个文件,并且需要超过24小时) Windows因此我想使用subprocess.call()
和rmdir
,但由于我的%PATH%
系统变量中有cygwin错误rmdir
被调用,我会得到这个:
>>> args = ['rmdir', r'D:\tmp']
>>> subprocess.call(args)
cygwin warning:
MS-DOS style path detected: D:\tmp
Preferred POSIX equivalent is: /cygdrive/d/tmp
CYGWIN environment variable option "nodosfilewarning" turns off this warning.
Consult the user's guide for more details about POSIX paths:
http://cygwin.com/cygwin-ug-net/using.html#using-pathnames
rmdir: failed to remove `D:\\tmp': Directory not empty
1
注意:我知道需要使用/S /Q
递归删除文件夹。
如何确保调用正确的rmdir
(例如在linux下使用绝对路径 - /bin/rm
),最好不使用使用shell=True
?< / p>
是否有替代实用程序(类似于使用robocopy /MIR
)?
我已经测试了使用Measure-Command
在 1,257,449个文件,750,251个文件夹中删除 237 GB(255,007,568,228个字节)的不同方法。
+-------------------+-------------+----------+-----------------+
| | rmdir /s /q | shutil | SHFileOperation |
+-------------------+-------------+----------+-----------------+
| Hours | 3 | 5 | 6 |
| Minutes | 26 | 52 | 14 |
| Seconds | 46 | 13 | 48 |
| TotalMinutes | 207 | 352 | 375 |
| TotalSeconds | 12406 | 21134 | 22488 |
| TotalMilliseconds | 12406040 | 21133805 | 22488436 |
+-------------------+-------------+----------+-----------------+
注意:测试是在生产服务器上运行的(因此结果可能会受到影响)
答案 0 :(得分:1)
rmdir
我想到了直接从cmd.exe /C
手动调用%SYSTEMROOT%\System32
并清除env
个变量的想法(它似乎有效):
def native_rmdir(path):
''' Removes directory recursively using native rmdir command
'''
# Get path to cmd
try:
cmd_path = native_rmdir._cmd_path
except AttributeError:
cmd_path = os.path.join(
os.environ['SYSTEMROOT'] if 'SYSTEMROOT' in os.environ else r'C:\Windows',
'System32', 'cmd.exe')
native_rmdir._cmd_path = cmd_path
# /C - cmd will terminate after command is carried out
# /S - recursively,
args = [cmd_path, '/C', 'rmdir', '/S', '/Q', path]
subprocess.check_call(args, env={})
native_rmdir(r'D:\tmp\work with spaces')
我认为无论系统范围PATH
如何,这都适用于任何版本的Windows,但我仍然更喜欢“elegant”。
将删除所有文件(第一次出错后不会停止)。
SHFileOperation()
也可以使用SHFileOperation()
执行此操作[example source]:
from win32com.shell import shell, shellcon
shell.SHFileOperation((0, shellcon.FO_DELETE, r'D:\tmp\del', None, shellcon.FOF_NO_UI))
在第一次出错后,将停止(当我在我的环境中测试此解决方案时,此解决方案往往比shutil.rmtree()
慢,可能是因为UI以某种方式涉及)。
答案 1 :(得分:1)
是的,我发现了这个别名,但是存在同样的问题......如果有人创建了rd.exe(或者已经安装在PATH变量中的任何地方),它就赢了#39工作。 在这种情况下它并没有真正重要,因为重点是无效的rmdir(来自cygwin的那个)被调用,我不想构建一个依赖于没有人的代码将在进程的cwd中创建文件rmdir.exe。
&#34>路径中的任何地方都是&#34;或关注的当前工作目录?如果它是cwd,那么:
if os.path.exists('rmdir.exe'):
raise BadPathError("don't run this in an insecure directory")
但潜在的问题是,您允许此操作从某人可以创建rmdir.exe
的目录运行。是的,Windows权限很弱,但解决起来并不难。
答案 2 :(得分:1)
使用内置插件os.walk
,os.remove
和os.rmdir
要注意的主要是Windows路径。使用/
作为路径分隔符而不是\
,或使用原始字符串。
但最好在路径名上使用os.path.normpath
,例如从命令行获取。
在随后的代码中,topdown=False
必需。
path = os.path.normpath(path)
for root, dirs, files in os.walk(path, topdown=False):
for f in files:
os.remove(os.path.join(root, f))
for d in dirs:
os.rmdir(os.path.join(root, d))
可能的速度改进可能是收集列表中的所有文件路径,并使用multiprocessing.Pool.map()
来使用多个进程删除文件。然后,您可以使用os.removedirs
来清空空目录。但是这个解决方案也可能会压倒磁盘子系统。
答案 3 :(得分:0)
根据记录here,rmdir
似乎有一个别名rd
。我无法测试它,但你可以尝试一下。
>>> args = ['rd', r'D:\tmp', '/s', '/q']
>>> subprocess.call(args)
删除隐藏文件或系统文件可能会有一些限制 - 再次我无法测试它。