112 lines
4.7 KiB
Python
112 lines
4.7 KiB
Python
import shutil
|
||
from pathlib import Path
|
||
|
||
|
||
def delete_duplicates_from_second_folder(source_dir: str, target_dir: str, dry_run: bool = False):
|
||
"""
|
||
删除第二个文件夹中与第一个文件夹内项目同名的文件或文件夹。
|
||
|
||
:param source_dir: 第一个文件夹(源)的路径。
|
||
:param target_dir: 第二个文件夹(目标)的路径,将从此文件夹中删除内容。
|
||
:param dry_run: 如果为True,则只打印将要删除的内容,而不实际执行删除操作。
|
||
"""
|
||
# 1. 将字符串路径转换为Path对象,方便操作
|
||
source_path = Path(source_dir)
|
||
target_path = Path(target_dir)
|
||
|
||
# 2. 验证路径是否存在且为文件夹
|
||
if not source_path.is_dir():
|
||
print(f"错误:源文件夹 '{source_dir}' 不存在或不是一个文件夹。")
|
||
return
|
||
if not target_path.is_dir():
|
||
print(f"错误:目标文件夹 '{target_dir}' 不存在或不是一个文件夹。")
|
||
return
|
||
|
||
print(f"源文件夹: {source_path}")
|
||
print(f"目标文件夹: {target_path}")
|
||
if dry_run:
|
||
print("\n--- *** 模拟运行模式 (Dry Run) *** ---")
|
||
print("--- 不会执行任何实际的删除操作 ---")
|
||
|
||
# 3. 获取源文件夹中所有项目(文件和子文件夹)的名称
|
||
# p.name 会返回路径的最后一部分,即文件名或文件夹名
|
||
source_item_names = {p.name for p in source_path.iterdir()}
|
||
|
||
if not source_item_names:
|
||
print("\n源文件夹为空,无需执行任何操作。")
|
||
return
|
||
|
||
print(f"\n在源文件夹中找到 {len(source_item_names)} 个项目。")
|
||
print("开始检查并删除目标文件夹中的同名项目...")
|
||
|
||
deleted_count = 0
|
||
# 4. 遍历源文件夹中的项目名称
|
||
for item_name in source_item_names:
|
||
# 构建目标文件夹中可能存在的同名项目的完整路径
|
||
item_to_delete = target_path / item_name
|
||
|
||
# 5. 检查该项目是否存在于目标文件夹中
|
||
if item_to_delete.exists():
|
||
try:
|
||
if item_to_delete.is_file():
|
||
# 如果是文件,直接删除
|
||
print(f"准备删除文件: {item_to_delete}")
|
||
if not dry_run:
|
||
item_to_delete.unlink()
|
||
print(" -> 已删除。")
|
||
deleted_count += 1
|
||
|
||
elif item_to_delete.is_dir():
|
||
# 如果是文件夹,使用 shutil.rmtree 删除整个文件夹及其内容
|
||
print(f"准备删除文件夹及其所有内容: {item_to_delete}")
|
||
if not dry_run:
|
||
shutil.rmtree(item_to_delete)
|
||
print(" -> 已删除。")
|
||
deleted_count += 1
|
||
|
||
except Exception as e:
|
||
print(f"!! 删除 '{item_to_delete}' 时发生错误: {e}")
|
||
|
||
if deleted_count == 0:
|
||
print("\n操作完成:在目标文件夹中没有找到需要删除的同名项目。")
|
||
else:
|
||
if dry_run:
|
||
print(f"\n模拟运行结束:如果实际运行,将会有 {deleted_count} 个项目被删除。")
|
||
else:
|
||
print(f"\n操作完成:总共删除了 {deleted_count} 个项目。")
|
||
|
||
|
||
# --- 使用示例 ---
|
||
|
||
# 在运行前,请创建以下文件夹和文件结构进行测试:
|
||
# /your/path/folder1/
|
||
# ├── file_a.txt
|
||
# ├── file_b.log
|
||
# └── subfolder_x/
|
||
# └── test.txt
|
||
|
||
# /your/path/folder2/
|
||
# ├── file_a.txt (将被删除)
|
||
# ├── file_c.md
|
||
# └── subfolder_x/ (将被删除)
|
||
# └── another.txt
|
||
|
||
if __name__ == '__main__':
|
||
# !! 重要:请将下面的路径修改为您自己电脑上的实际路径
|
||
folder1_path = "D:/download/2025-10/after_step5/after_step5/S" # 源文件夹
|
||
folder2_path = "D:/download/2025-10/input/input" # 目标文件夹
|
||
|
||
# --- 第一次运行:使用模拟模式 (Dry Run),非常推荐!---
|
||
# 这会告诉你脚本将要做什么,但不会真的删除任何东西。
|
||
print("================ 第一次运行: 模拟模式 ================")
|
||
delete_duplicates_from_second_folder(folder1_path, folder2_path, dry_run=True)
|
||
|
||
print("\n\n=======================================================")
|
||
input("检查上面的模拟运行结果。如果符合预期,按回车键继续执行实际删除操作...")
|
||
print("=======================================================")
|
||
|
||
# --- 第二次运行:实际执行删除 ---
|
||
# 确认模拟运行结果无误后,再将 dry_run 设置为 False 或移除该参数。
|
||
print("\n================ 第二次运行: 实际删除模式 ================")
|
||
delete_duplicates_from_second_folder(folder1_path, folder2_path, dry_run=False)
|