python程序小工具——对比两个文件夹差异

写在前面:

功能说明:给了两个文件夹,需要对比出两个文件夹的文件不同之处,包括前一个文件夹比后一个文件夹减少了哪些文件或子文件夹,亦或是后一个比前一个多了多少。

思路:

根据当下的要求,只是简单对比两个文件夹的文件名的异同。

说明扩展:

1、由于当前的程序只是对比了文件名相同与否,并不能保证后一个文件夹中的文件是否只是文件名相同,但是文件内容已经进行了修改。如果需要对比确保文件是否修改,可以在获取当前文件夹下文件的函数get_files里面,添加记录文件的最后修改时间,与文件名进行拼接组合成key,这样在后续两文件夹对比时也可以分离出修改时间。

2、同样地,该程序同样没有对比文件扩展名,如果需要对比不同的文件格式,方法同上,也是保留拓展名放置于key中。

import os
import shutil
import time
from collections import defaultdict


def make_dir(file_path, file_name = None):
    """
    创建文件夹
    :param file_path:
    :return:
    """
    if file_name is not None:
        file_path = os.path.join(file_path, file_name)
    try:
        os.mkdir(file_path)
    except FileExistsError:
        print('文件夹已存在')


def get_files(file_path):
    """
    获取当前绝对路径下的所有文件名
    :param file_path: 文件夹绝对路径
    :return: 记录文件的路径字典,记录文件夹的路径字典
    """
    file_list = os.listdir(file_path)
    # 当前文件夹下所有文件和文件夹的列表,key为文件名(不含拓展名),value为该文件的绝对路径
    file_dict = defaultdict(str)
    dir_dict = defaultdict(str)
    for file in file_list:
        # print(file)
        file_item = os.path.join(file_path, file)
        if os.path.isfile(file_item):
            # 判断是否是文件
            file_name = file.rsplit('.', 1)[0]
            file_dict[file_name] = file_item
        elif os.path.isdir(file_item):
            file_name = file.rsplit('.', 1)[0]
            dir_dict[file_name] = file_item
    return file_dict, dir_dict


def move_file_to_dir(file_path, file_name, dir_path):
    """
    把文件移动到文件夹下面
    :param file_path:文件所处的文件夹路径
    :param file_name:文件名
    :param dir_path:所要移动到的目标文件夹
    :return:
    """
    try:
        if dir_path is None or file_path is None:
            return
        file_name = os.path.join(file_path, file_name)
        shutil.copy2(file_name, dir_path)
    except Exception as e:
        print("{}-->{}复制文件失败".format(file_name, dir_path))


def move_dir_to_dir(from_dir_path, to_dir_path):
    """
    把文件夹移动到目标文件夹下面
    :param from_dir_path:所要移动的文件夹
    :param to_dir_path:目标文件夹
    :return:
    """
    try:
        from_dir_name = from_dir_path.rsplit("\\", 1)[1]
        to_dir_path = os.path.join(to_dir_path, from_dir_name)
        shutil.copytree(from_dir_path, to_dir_path)
    except Exception as e:
        print("{}-->{}复制文件夹失败".format(from_dir_path, to_dir_path))


def del_files(file_path, file_name = None):
    """
    删除文件
    :param file_path:文件所处的文件夹路径
    :param file_name:文件名,如果是None,则file_path需要是要删除文件的绝对路径
    :return:
    """
    if file_name is not None:
        file_path = os.path.join(file_path, file_name)
    if os.path.isfile(file_path):
        # 删除文件
        os.remove(file_path)


def del_dir(file_path):
    """
    删除空白的文件夹
    :param file_path:文件夹绝对路径
    :return:
    """
    judge = True
    # 遍历路径下的所有文件夹和文件
    for root, dirs, files in os.walk(file_path, topdown=False):
        # 如果文件夹为空
        if not dirs and not files and root != file_path:
            # 删除该文件夹
            os.rmdir(root)
            judge = False
            print(f"Removing empty dir {root}")
    return judge


def compare_files(old_folder_path, new_folder_path, add_path, sub_path):
    """
    对比两个新旧文件夹文件,注意,这里的都是文件名,需要结合路径进行拼接
    :param old_folder_path:旧的文件夹绝对路径
    :param new_folder_path:新的文件夹绝对路径
    :return:
    """
    # 定义增加的文件夹路径和减的文件夹路径
    if os.path.exists(add_path):
        pass
    else:
        make_dir(add_path)
    if os.path.exists(sub_path):
        pass
    else:
        make_dir(sub_path)
    # 第一步,获取新旧文件夹中的
    old_files_dict,  old_dir_dict = get_files(file_path=old_folder_path)
    new_files_dict,  new_dir_dict = get_files(file_path=new_folder_path)
    # 第二步,对比新旧文件夹中的文件列表,统计出多的文件和少的文件
    add_files = set(new_files_dict.keys()) - set(old_files_dict.keys())
    sub_files = set(old_files_dict.keys()) - set(new_files_dict.keys())
    # 第三步,在增和减中创建当前文件夹路径,将多的文件移动到增文件夹对应中,少的放到减对应中
    # 增加文件
    if len(add_files) > 0:
        for add_item in add_files:
            add_file_item = new_files_dict.get(add_item)
            move_file_to_dir(file_path=new_folder_path, file_name=add_file_item, dir_path=add_path)
    # 减少文件
    if len(sub_files) > 0:
        for sub_item in sub_files:
            sub_file_item = old_files_dict.get(sub_item)
            move_file_to_dir(file_path=old_folder_path, file_name=sub_file_item, dir_path=sub_path)

    # 第四步,对比多和少的文件夹,如果多的,放入增,少的放入减
    add_dir = set(new_dir_dict.keys()) - set(old_dir_dict.keys())
    sub_dir = set(old_dir_dict.keys()) - set(new_dir_dict.keys())
    if len(add_dir) > 0:
        for add_item in add_dir:
            add_dir_item = new_dir_dict.get(add_item)
            move_dir_to_dir(from_dir_path=add_dir_item,  to_dir_path=add_path)

    # 减少文件
    if len(sub_dir) > 0:
        for sub_item in sub_dir:
            sub_dir_item = old_dir_dict.get(sub_item)
            move_dir_to_dir(from_dir_path=sub_dir_item,  to_dir_path=sub_path)

    # 第五步,进入都有的文件夹中,继续step
    both_dir_names = set(new_dir_dict.keys()) & set(old_dir_dict.keys())
    for both_dir_item in both_dir_names:
        add_path_new = os.path.join(add_path, both_dir_item)
        sub_path_new = os.path.join(sub_path, both_dir_item)
        compare_files(old_folder_path=os.path.join(old_folder_path, both_dir_item),
                      new_folder_path=os.path.join(new_folder_path, both_dir_item),
                      add_path=add_path_new, sub_path=sub_path_new)


######################
# 配置信息
######################
old_folder_path = "old_folder_path"
new_folder_path = "new_folder_path"
old_folder_name = old_folder_path.split("\\")[-1]
new_folder_name = new_folder_path.split("\\")[-1]
root_folder_path = old_folder_path.rsplit("\\", 1)[0]
# 对比结果的文件夹名
compare_file_path = "《{}》到《{}》的差异对比结果".format(old_folder_name, new_folder_name)
# 对比结果文件夹的放置路径,与新文件夹的路径平行
total_file_compare_path = os.path.join(root_folder_path, compare_file_path)
# 如果当前文件夹下有对比对比结果的文件夹,则创建的文件夹名字后缀加上当前系统时间最后四位
if os.path.exists(total_file_compare_path):
    compare_file_path += str(time.time())[-4:]
    total_file_compare_path = os.path.join(root_folder_path, compare_file_path)
# 文件夹的新增文件放置的文件夹路径,绝对路径
total_add_file_compare_path = os.path.join(total_file_compare_path, "新增")
# 文件夹的减少文件放置的文件夹路径,绝对路径
total_sub_file_compare_path = os.path.join(total_file_compare_path, "减少")
# 创建以上文件夹
make_dir(root_folder_path, compare_file_path)
make_dir(total_add_file_compare_path)
make_dir(total_sub_file_compare_path)

if __name__ == "__main__":
    # 第一步,获取所有比较的文件
    compare_files(old_folder_path=old_folder_path, new_folder_path=new_folder_path, add_path=total_add_file_compare_path, sub_path=total_sub_file_compare_path)
    # 删除空的文件夹
    while True:
        if del_dir(total_add_file_compare_path) and del_dir(total_sub_file_compare_path):
            break

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值