发现重复的图片有点多,手动对比去重有点麻烦。用Python编写了一个去重图片脚本,结合昨天文章中的进度条功能。这个脚本的主要功能是扫描指定目录及其子目录中的图像文件,并根据文件内容的MD5哈希值来判断是否存在重复文件。如果存在重复文件,用户可以选择是否删除这些重复文件。以下是代码:
代码:
import
os
import
hashlib
from
collections
import
defaultdict
def
get_file_md5
(file_path)
:
"""计算文件的MD5值"""
with
open(file_path,
'rb'
)
as
f:
file_hash = hashlib.md5()
while
chunk := f.read(
8192
):
file_hash.update(chunk)
return
file_hash.hexdigest()
def
hacker_progress_bar
(iteration, total, prefix=
''
, suffix=
''
, decimals=
1
, length=
100
, fill=
'█'
)
:
"""
进度条特效函数
:param iteration: 当前迭代次数
:param total: 总进度
:param prefix: 进度条前缀
:param suffix: 进度条后缀
:param decimals: 进度小数位数
:param length: 进度条长度
:param fill: 进度条填充字符
"""
if
total ==
0
:
return
percent = (
"{0:."
+ str(decimals) +
"f}"
).format(
100
* (iteration / float(total)))
filled_length = int(length * iteration // total)
bar = fill * filled_length +
'-'
* (length - filled_length)
print(
f'r
{prefix}
|
{bar}
|
{percent}
%
{suffix}
'
, end=
'r'
)
if
iteration == total:
print()
def
remove_duplicate_images
(directory)
:
"""删除目录中重复的图像文件"""
image_files = []
for
root, _, files
in
os.walk(directory):
for
filename
in
files:
if
filename.lower().endswith((
'.png'
,
'.jpg'
,
'.jpeg'
,
'.gif'
,
'.bmp'
)):
file_path = os.path.join(root, filename)
image_files.append(file_path)
total_files = len(image_files)
if
total_files ==
0
:
print(
"去重复图片脚本---微信公众号:蓝胖子之家"
)
print(
""
)
print(
""
)
print(
f"目录
{directory}
中没有图像文件。"
)
input(
"按下回车键退出..."
)
return
print(
"去重复图片脚本---微信公众号:蓝胖子之家"
)
print(
""
)
print(
""
)
print(
f"正在扫描目录
{directory}
中的图像文件..."
)
hacker_progress_bar(
0
, total_files, prefix=
'Progress:'
, suffix=
'Scanning'
, length=
50
)
image_md5s = defaultdict(list)
for
i, file_path
in
enumerate(image_files):
md5 = get_file_md5(file_path)
image_md5s[md5].append(file_path)
hacker_progress_bar(i+
1
, total_files, prefix=
'Progress:'
, suffix=
'Scanning'
, length=
50
)
duplicate_files = [paths[
1
:]
for
md5, paths
in
image_md5s.items()
if
len(paths) >
1
]
if
duplicate_files:
print(
f"n发现共有
{len(duplicate_files)}
组重复图片文件:"
)
for
index, files
in
enumerate(duplicate_files,
1
):
print(
f"组
{index}
:"
)
for
file
in
files:
print(
f"
{file}
"
)
remove_duplicates = input(
"是否删除重复图片文件? (y/n) "
)
if
remove_duplicates.lower() ==
'y'
:
for
files
in
duplicate_files:
for
duplicate_file
in
files:
os.remove(duplicate_file)
print(
f"已删除文件:
{duplicate_file}
"
)
else
:
print(
"未发现重复图片文件。"
)
input(
"按下回车键退出..."
)
if
__name__ ==
"__main__"
:
current_directory = os.getcwd()
remove_duplicate_images(current_directory)
-
get_file_md5
函数:
-
这个函数接受一个文件路径作为参数,并计算该文件的MD5哈希值。
-
使用
hashlib
模块的md5
方法创建一个MD5对象,然后使用update
方法逐步更新哈希值。 -
函数使用
rb
模式打开文件,以二进制形式读取文件内容。 -
使用
read
方法读取文件的一部分内容,并使用update
方法更新哈希值。 -
最后,使用
hexdigest
方法获取最终的MD5哈希值,并将其以十六进制字符串的形式返回。
-
hacker_progress_bar
函数:
-
这个函数用于在控制台中显示进度条。
-
函数接受多个参数,包括当前迭代次数、总进度、进度条前缀和后缀、进度小数位数、进度条长度和填充字符。
-
函数根据当前迭代次数和总进度计算进度百分比,并使用给定的填充字符和长度创建进度条字符串。
-
使用
r
符号实现在同一行上覆盖显示进度条。 -
当迭代次数等于总进度时,输出一个换行符,以完成进度条的显示。
-
remove_duplicate_images
函数:
-
这个函数接受一个目录路径作为参数,并执行删除重复图像文件的操作。
-
函数首先获取目录下所有的图像文件,并将它们的文件路径存储在一个列表中。
-
如果目录中没有图像文件,则输出相应的提示信息,并退出函数。
-
接下来,函数使用
hacker_progress_bar
函数显示扫描进度条,并初始化一个空的字典image_md5s
用于存储图像文件的MD5哈希值和文件路径。 -
使用
enumerate
函数遍历图像文件列表,并对每个文件计算MD5哈希值。 -
将哈希值作为键,将文件路径添加到对应的值列表中。
-
扫描过程完成后,函数检查字典中的值列表长度是否大于1,如果大于1,则表示存在重复图像文件。
-
如果存在重复图像文件,函数会输出重复文件的组数和每个组中的文件路径。
-
最后,函数询问用户是否删除重复图像文件。如果用户选择删除,函数会遍历每个重复文件组,并使用
os.remove
函数删除重复文件。
-
__main__
块:
-
这个块获取当前工作目录,并将其作为参数调用
remove_duplicate_images
函数。 -
运行脚本时,会提示用户输入要扫描的目录路径。
-
脚本会根据用户输入的目录路径进行扫描,并根据需要删除重复图像文件。
运行效果:
原文始发于微信公众号(蓝胖子之家):Python写去重脚本根据MD5哈希值扫描重复图片并删除
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论