ホームページ  >  記事  >  バックエンド開発  >  Python を使用して Windows で長いパスのファイルを段階的に削除する

Python を使用して Windows で長いパスのファイルを段階的に削除する

王林
王林転載
2023-04-12 13:31:081183ブラウズ

0x01 記事の背景

最近、著者の会社の業務システムのストレージが限界に近づき、業務システム A には複数のサブシステム A1、A2 が含まれているため、間もなくサーバーが稼働できなくなります。 、A3. .. 設計上の理由により、これらのサブシステムの中間ストレージ ファイルはすべて同じ親ディレクトリに格納されます。唯一の違いは、異なるサブシステムによって生成されたファイルとフォルダーの名前はすべて、次の名前で始まることです。サブシステム。たとえば、A1 サブシステムによって生成されるファイル名はすべて A1xxxxxx で、A2 サブシステムによって生成されるファイル名はすべて A2xxxxx です。ここで、サーバーのスペースを解放するために、これらのサブシステムの一部の履歴ファイルを削除する必要があります。数十テラバイトのデータが一緒に保存されています。手動での削除は絶対に表示されません。これを実現するには、プログラムの自動化を使用するしかありません。何を使用すればよいですか? ?当然Pythonを思い浮かべました。実際、単にファイルを削除する必要性については、長々と議論する価値はないと思いますが、いくつかの特殊で興味深い問題と興味深い解決策に遭遇したので、非常に長いファイルの削除など、それらを共有したいと思います。 Windows システムでは、英語の公式ドキュメントを読んで解決策を見つけるなどしてください。本題に入りましょう。

0x02 Python を使用してファイルを削除する

Python を使用してファイルを削除する方法は多数あります。最も直接的で便利な方法は、組み込み関数を呼び出すことです:

  • os.remove () ファイルを削除します
  • os.rmdir() 空のフォルダーを削除します
  • shutil.rmtree() フォルダーとそのフォルダー内のすべての内容 (サブディレクトリとファイルを含む) を削除します

つまり、この問題の解決の核心は、上記の 3 つの機能に対処することです。発生した問題に目を向けると、ビジネス システム A には複数のサブシステム A1、A2、A3...An が含まれています。設計上の理由により、これらのサブシステムの中間ストレージ ファイルはすべて同じ親ディレクトリに格納されています。唯一の違いは、はい、ということです。さまざまなサブシステムによって生成されるファイルとフォルダーの名前はすべてサブシステム名で始まります。たとえば、A1 サブシステムによって生成されたファイルの名前はすべて A1xxxxxx で、A2 サブシステムによって生成されたファイル名はすべて A2xxxxx です。ここでの目的は、指定されたサブシステムによって生成されたファイルを削除し、他のサブシステムのファイルを保持することです。

要件を詳しく分析すると、実際には次の 4 つの問題が解決されます:

1. ファイルを削除するにはどうすればよいですか?

2. ファイルまたはフォルダーが特定のサブシステムによって生成されたものであることを識別するにはどうすればよいですか?

3. パスがファイルなのかディレクトリなのかを判断するにはどうすればよいですか?

4. 指定されたすべてのサブシステムによって生成されたファイルとフォルダーを見つけるにはどうすればよいですか?

質問 1 については、このセクションの冒頭で説明したように、Python の組み込み関数を使用して削除できます。

os.remove("path") # 删除指定文件
os.rmdir("path") # 删除一个空文件夹
shutil.rmtree("path") #删除一个文件夹及该文件夹下所有内容(包括子目录及文件)

質問 2 については、特定のサブシステムによって生成されたファイルとフォルダーメソッドはすべて固定パターンであり、たとえば、A1 サブシステムによって生成されるファイル名はすべて A1xxxxx であるため、キーワード マッチングによって識別できます。考えられる方法の 1 つは次のとおりです。

if keywords in filepath: # 如果文件名包含关键字keywords
os.remove(filepath) # 删除文件
else:
pass

質問 3 では、ディレクトリの削除とファイルの削除の方法が一致していないため、削除する前にパスがディレクトリであるかファイルであるかを判断し、適切な削除を選択する必要があります。これは、Python で **os.path.isdir()** などの関数、主に次の関数を使用して決定できます:

os.path.isdir("path") # 返回true则为目录,false则为文件
os.path.isfile("path") # 返回true则为文件,false则为目录

質問 4 では、すべてのファイルを見つける方法実際、この質問は、指定されたディレクトリ内のファイルを走査する問題、つまり、指定されたディレクトリ内のすべてのフォルダとファイルをどのように走査するかという問題です。この問題に対しては、一般に 2 つの解決策があります。1 つは深さ優先トラバーサル方法で、もう 1 つは幅優先トラバーサル方法です。この例では、最終的にすべてをトラバースする必要があるため、2 つの方法の効率は同じです。ファイル。さらに、幸いなことに、Python は非常に強力なので、その組み込み関数は、幅優先ディレクトリ トラバーサル メソッドと、パス ディレクトリ内のすべてのファイルをトラバースする os.walk("path") メソッドの実装に役立ちました。

import os

path = "C:\A\"

for root, dirs, files in os.walk(path):
print(root)
print(dirs)
print(files)

上の例では、root は現在通過しているパスを表し、dirs は現在のパスの下のすべてのサブディレクトリを表し、files は現在のパスの下のすべてのサブファイルを表します。このようにして、指定されたすべてのディレクトリを横断することができます。

問題は分解されました。問題を結合してコード実装を完成させましょう。

最終的なコード実装は次のとおりです:

import os
import shutil

path = "C:\A\"
keyword = "A1"

for root, dirs, files in os.walk(path):
for dir in dirs:
if keyword in dir:
rmpath = os.path.join(root, dir)
print("删除文件夹: %s" % rmpath)
shutil.rmtree(rmpath)
for file in files:
if keyword in file:
rmpath = os.path.join(root, file)
print("删除文件: %s" % rmpath)
os.remove(rmpath)

つまり、幅優先法 ( os.walk()) は、指定されたディレクトリを走査し、ディレクトリ内のすべてのサブディレクトリとファイルがキーワード条件を満たしているかどうかを 1 つずつ判断し、満たしている場合はそれらを削除します。

実行結果は次のとおりです:

Python を使用して Windows で長いパスのファイルを段階的に削除する

この時点で要件は基本的に解決されているように見えますが、実際のテストでは非常に深いディレクトリがいくつか見つかりました。しかし、削除されませんでした。ディレクトリの削除中にエラーが発生しました。エラーの説明は次のとおりです:

Unexpected error: (< type 'exceptions.WindowsError'>, WindowsError(3, 'The system cannot find the path specified'), < traceback object at 0x0000000002714F88>)

大致意思就是python找不到这个路径,可是为什么呢?为此,我继续进行一番资料查询,后来大致定位了是由于文件路径过长导致的,是由于windows系统用户态的默认路径长度不能超过256个字节导致的。但是官方说256个字节是最长,但为何能创建超过256的呢,所以既然能创建,那就一定能删除,但是需要一些方法,经过一番学习,找到了好几种方法,下面介绍其中一种最为实用的方法,另外几个比如使用压缩软件压缩后删除(百度知道的结果)适合手动但不适合编程解决。这个方法在下一节中继续讲述。

0x03 windows 文件系统关于长路径文件的相关定义

为解决windows下的长文件删除的问题,最为权威的资料莫过于windows官方的描述,我阅读了微软关于文件名长度的这一块的定义及说明,找到解决方案,微软的原文如下:

Python を使用して Windows で長いパスのファイルを段階的に削除する

关键意思如下:

1.Windows API 提供的文件路径理论上最长是 32767 个字节,普通状态下给用户使用是不超过256个字符,说是为了使用户操作更加方便。这里不得不吐槽一下了,确实操作方便了,但是方便的同时也可能带来不便,明明定义了32767这么长的字节,只给用256,未免太抠搜了一点

2.用户如果想要打破这个长度限制,可以通过一个特殊方式告诉windows系统自己想要使用超长文件,这个特殊的方式就是在绝对路径前加上** "?" **字符串。

3.这篇文档后面还有描述在windows10以后如何通过注册表的方式接触文件名长度限制,这里就没有截图了,因为不通用,win7怎么办呢?有兴趣的同学可以查看其原文链接阅读:https://docs.microsoft.com/en-US/windows/win32/fileio/maximum-file-path-limitation?tabs=cmd

好了,看到这,解决方法呼之欲出,其实简单得不能太简单,直接在绝对路径前加上一个"?"即可:

# 获取目标路径的绝对路径,并在路径前加上\?,
# 以解除windows的文件长度限制
path = '\\?\' + os.path.abspath(path)

0x04 改造 python 程序,删除长路径文件

根据上一节,对python程序进一步进行改造,加入windows长文件名限制解除,最后的完美删除工具就成型了:

import os
import shutil

path = "C:\A\"
keyword = "A1"

# 获取目标路径的绝对路径,并在路径前加上\?,
# 以解除windows的文件长度限制
path = '\\?\' + os.path.abspath(path)

for root, dirs, files in os.walk(path):
for dir in dirs:
if keyword in dir:
rmpath = os.path.join(root, dir)
print("删除文件夹: %s" % rmpath)
shutil.rmtree(rmpath)
for file in files:
if keyword in file:
rmpath = os.path.join(root, file)
print("删除文件: %s" % rmpath)
os.remove(rmpath)

虽然代码很短,只添加了一行,但是这一行,却完成了一个超级核心的任务,真可谓是灵魂一行啊,最后该工具中如在生产环境中发挥了其出色的作用,使服务器继续运转如飞了。

0x04 总结思考

啰嗦的话就不多说了,说几点思考 :

1.遇到问题将问题进行分解,拆分成一个个小问题逐步击破 。

2.要善于阅读官方技术文档,有时候解决一个问题的核心可能很简单,代码可能也就一行两行,但是就是藏在某个角落,不仔细去阅读还真不一定找得出来 。

3.python是个好东西,要有将问题转化成使用python去解决的习惯,习惯成自然,python可能在工作中就发挥大作用了呢。

0x05 参考资料

1.https://docs.microsoft.com/en-US/windows/win32/fileio/maximum-file-path-limitation?tabs=cmd  

2.https://stackoverflow.com/questions/6996603/how-to-delete-a-file-or-folder-in

以上がPython を使用して Windows で長いパスのファイルを段階的に削除するの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事は51cto.comで複製されています。侵害がある場合は、admin@php.cn までご連絡ください。