Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/windows/17.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 快速递归文件夹删除-调用正确的rmdir_Python_Windows - Fatal编程技术网

Python 快速递归文件夹删除-调用正确的rmdir

Python 快速递归文件夹删除-调用正确的rmdir,python,windows,Python,Windows,这个问题并没有直接与python联系在一起,但我需要在windows下的python32下工作实现 从这一点开始,我假设在windows下使用非常慢(我每天需要删除超过3M个文件,需要24小时以上),所以我想使用和rmdir,但由于我的%PATH%系统变量中有cygwin错误rmdir被调用,我将得到以下结果: >>> args = ['rmdir', r'D:\tmp'] >>> subprocess.call(args) cygwin warning:

这个问题并没有直接与python联系在一起,但我需要在windows下的python32下工作实现

从这一点开始,我假设在windows下使用非常慢(我每天需要删除超过3M个文件,需要24小时以上),所以我想使用和
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

是否有其他实用程序(如使用)


编辑:速度比较 我已经使用测试了在1257449个文件、750251个文件夹中删除237GB(255007568228字节)的不同方法

+-------------------+-------------+----------+-----------------+
|| rmdir/s/q | shutil | SHFileOperation|
+-------------------+-------------+----------+-----------------+
|工作时间| 3 | 5 | 6|
|会议记录| 26 | 52 | 14|
|秒| 46 | 13 | 48|
|总分钟数| 207 | 352 | 375|
|总秒数12406 | 21134 | 22488|
|总毫秒数| 12406040 | 2113805 | 22488436|
+-------------------+-------------+----------+-----------------+
注意:测试是在生产服务器上运行的(因此结果可能会受到影响)

如文件所述,
rmdir
似乎有一个别名,
rd
。我无法测试,但你可以试试这个

>>> args = ['rd', r'D:\tmp', '/s', '/q']
>>> subprocess.call(args)
删除隐藏文件或系统文件时可能会有一些限制-同样,我无法测试它。

调用适当的
rmdir
我想出了一个主意,直接从
%SYSTEMROOT%\System32
手动调用
cmd.exe/C
,并清除
env
变量(这似乎有效):

我假设这在任何版本的windows下都能工作,无论系统范围是
路径,但我还是更喜欢更“优雅”的东西

删除它可以删除的所有文件(在第一个错误后,不会停止)


使用 也可以使用
SHFileOperation()
执行此操作:

将在第一个错误后停止(当我在我的环境中测试此解决方案时,此解决方案往往比
shutil.rmtree()
慢,可能是因为不知何故涉及到UI)


是的,我找到了这个别名,但也有同样的问题。。。如果有人创建了rd.exe(或在PATH变量的任何位置安装了get),它将无法工作。 在这种情况下这并不重要,因为关键是调用了无效的rmdir(来自cygwin的rmdir)get,我不想构建一个依赖于没有人会在进程的cwd中创建文件rmdir.exe的代码

那么,“路径中的任何地方”或当前的工作目录是问题所在吗?如果是cwd,那么:

 if os.path.exists('rmdir.exe'):
     raise BadPathError("don't run this in an insecure directory")

但是潜在的问题是,您允许它从一个目录运行,在这个目录中有人可以创建
rmdir.exe
。是的,Windows权限很弱,但解决起来并不难。

使用内置的
os.walk
os.remove
os.rmdir

要注意的主要问题是Windows路径。使用
/
作为路径分隔符而不是
\
,或者使用原始字符串

但是,最好对从命令行获取的路径名使用
os.path.normpath

在下面的代码中,
top-down=False
是必不可少的


一种可能的速度改进可能是将所有文件路径收集到一个列表中,并将其与
multiprocessing.Pool.map()
一起使用以删除使用多个进程的文件。之后,您可以使用
os.removedirs
清除空目录。但是,此解决方案也可能会淹没磁盘子系统。

如果您的路径中有cygwin,则始终可以使用
rm-rf
。您遇到的错误似乎与目录不为空有关。如果其中有文件,Windows将抛出此错误。添加
/s
开关使其递归?@FatalError不幸的是,脚本将在多台机器上运行,我不能依靠它们来安装cygwin(我可以检查cygwin并调用cygwin等等,但我想要一个优雅而简单的解决方案)@taddh我在这种情况下并不重要,因为关键是调用了无效的
rmdir
(来自cygwin的那一个)get,我不想构建一个依赖于任何人的代码,没有人会在进程的
cwd
中创建文件
rmdir.exe,但也有同样的问题。。。如果有人创建了
rd.exe
(或者get安装在
路径
变量中的任何位置),它将不起作用。可能我没有抓住要点,但为什么有人要创建
rd.exe
?我可以理解
rmdir
对于安装了cygwin的用户来说是个问题,但是
rd
不是cygwin命令。
shutil.rmtree()
在您的环境中真的那么慢吗?它每天要删除超过300万个文件,而且批量大小超过24小时。这是我建议的解决方案,我认为它足够优雅-您需要一个特定的shell,您可以直接调用它。我发现您的第一个解决方案是最好的
rd
是一个内部命令,而不是二进制(外部)命令,因此自然地,
cmd.exe
是您必须为i调用的命令
from win32com.shell import shell, shellcon
shell.SHFileOperation((0, shellcon.FO_DELETE, r'D:\tmp\del', None, shellcon.FOF_NO_UI))
 if os.path.exists('rmdir.exe'):
     raise BadPathError("don't run this in an insecure directory")
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))