吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 411|回复: 14
收起左侧

[经验求助] 请各位大佬帮忙合并PY脚本,两个功能合为一个

[复制链接]
llyaomo 发表于 2024-6-21 16:16
25吾爱币
本帖最后由 llyaomo 于 2024-6-21 16:27 编辑

如题,我百度智能生成了两段代码,第一段目的是将文件按照修改日期分类整理,第二段目的是将文件夹按照修改日期分类整理,其实我起初的目标是将两个功能合二为一,可是百度AI不够聪明,实现不了。现在求助会PY的各位大佬,帮我合并两段代码,功能合二为一,不胜感激。


import os
import shutil
import hashlib
from datetime import datetime
import tkinter as tk
from tkinter import filedialog

# 创建一个Tk窗口实例
root = tk.Tk()
root.withdraw()  # 隐藏主窗口

# 打开文件夹选择对话框
source_folder = filedialog.askdirectory()

# 打印选择的文件夹路径
if source_folder:
    print("输入的待整理文件夹地址是:", source_folder)
else:
    print("未选择文件夹")

    # 打开文件夹选择对话框
destination_folder = filedialog.askdirectory()

# 打印选择的文件夹路径
if destination_folder:
    print("输入的目标文件夹地址是:", destination_folder)
else:
    print("未选择文件夹")

def get_week_and_year(mtime):
    """根据修改时间获取年份和周数"""
    date = datetime.fromtimestamp(mtime)
    year = date.year
    month = date.month
    week = date.strftime('%V')  # ISO 8601 周数
    return year, month, week

def get_file_md5(file_path):
    """获取文件的MD5哈希值"""
    hash_md5 = hashlib.md5()
    with open(file_path, "rb") as f:
        for chunk in iter(lambda: f.read(4096), b""):
            hash_md5.update(chunk)
    return hash_md5.hexdigest()

def organize_files_by_date(source_dir, dest_dir):
    """按照修改日期组织文件和文件夹,并处理同名文件的md5冲突"""
    if not os.path.exists(dest_dir):
        os.makedirs(dest_dir)

    for item in os.listdir(source_dir):
        item_path = os.path.join(source_dir, item)
        if os.path.isfile(item_path):
            mtime = os.path.getmtime(item_path)
            year, month, week = get_week_and_year(mtime)
            path1 = '年'
            path3 = '周'

            dest_base_path = os.path.join(dest_dir, str(year)+path1, f"{month:02d}月", str(week)+path3)
            if not os.path.exists(dest_base_path):
                os.makedirs(dest_base_path)

            dest_file_path = os.path.join(dest_base_path, item)
            if os.path.exists(dest_file_path):
                # 如果目标文件已存在,比较MD5
                dest_md5 = get_file_md5(dest_file_path)
                source_md5 = get_file_md5(item_path)
                if dest_md5 == source_md5:
                    # MD5相同,选择覆盖
                    shutil.move(item_path, dest_file_path)
                else:
                    # MD5不同,选择重命名
                    base, ext = os.path.splitext(item)
                    counter = 1
                    new_dest_file_path = dest_file_path
                    while os.path.exists(new_dest_file_path):
                        new_dest_file_path = os.path.join(dest_base_path, f"{base}_{counter}{ext}")
                        counter += 1
                    shutil.move(item_path, new_dest_file_path)
            else:
                # 目标文件不存在,直接复制
                shutil.move(item_path, dest_file_path)

# 使用示例
# source_folder = input("请输入需要整理的文件夹路径: ")
# destination_folder = input("请输入目标文件夹路径: ")

organize_files_by_date(source_folder, destination_folder)


import os
import shutil
import datetime
import tkinter as tk
from tkinter import filedialog

# 创建一个Tk窗口实例
root = tk.Tk()
root.withdraw()  # 隐藏主窗口

# 打开文件夹选择对话框
source_directory = filedialog.askdirectory()

# 打印选择的文件夹路径
if source_directory:
    print("输入的待整理文件夹地址是:", source_directory)
else:
    print("未选择文件夹")

    # 打开文件夹选择对话框
destination_directory = filedialog.askdirectory()

# 打印选择的文件夹路径
if destination_directory:
    print("输入的目标文件夹地址是:", destination_directory)
else:
    print("未选择文件夹")

def get_year_month_week(folder_path):
    mtime = os.path.getmtime(folder_path)
    modified_date = datetime.datetime.fromtimestamp(mtime)
    year = modified_date.year
    month = modified_date.month
    week = modified_date.isocalendar()[1]
    return year, month, week

def move_or_rename_folder(source_folder, dest_path):
    # 获取源文件夹的详细信息
    source_name = os.path.basename(source_folder)
    source_size = sum(
        os.path.getsize(os.path.join(root, file)) for root, dirs, files in os.walk(source_folder) for file in files)

    # 检查目标路径是否存在同名文件夹
    target_folder = os.path.join(dest_path, source_name)
    if os.path.exists(target_folder):
        # 如果存在,比较大小
        target_size = sum(
            os.path.getsize(os.path.join(root, file)) for root, dirs, files in os.walk(target_folder) for file in files)
        if source_size == target_size:
            print(f"Skipping {source_folder} because a folder with the same name and size already exists.")
            return

    # 如果不存在同名文件夹或大小不同,移动或重命名文件夹
    base_name, ext = os.path.splitext(source_name)
    counter = 1
    new_name = source_name
    while os.path.exists(os.path.join(dest_path, new_name)):
        new_name = f"{base_name}_{counter}{ext}"
        counter += 1

    shutil.move(source_folder, os.path.join(dest_path, new_name))
    print(f"Moved or renamed {source_folder} to {os.path.join(dest_path, new_name)}")

def organize_folders_by_date(source_dir, dest_dir):
    if not os.path.exists(dest_dir):
        os.makedirs(dest_dir)

    for item in os.listdir(source_dir):
        item_path = os.path.join(source_dir, item)
        if os.path.isdir(item_path):
            year, month, week = get_year_month_week(item_path)

            # 创建目标文件夹路径
            target_path = os.path.join(dest_dir, f"{year}年", f"{month:02d}月", f"{week:02d}周")

            # 确保目标路径存在
            if not os.path.exists(target_path):
                os.makedirs(target_path)

            # 移动或重命名文件夹
            move_or_rename_folder(item_path, target_path)

# 使用示例
# source_directory = input("请输入源文件夹地址:")  # 源文件夹路径
# destination_directory = input("请输入目标文件夹地址:")  # 目标文件夹路径
organize_folders_by_date(source_directory, destination_directory)

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

 楼主| llyaomo 发表于 2024-6-24 08:29
顶起,希望能有PY大佬赏脸光顾
莫谷 发表于 2024-6-24 08:39
为啥非得合并呢?你是觉得运行两次够麻烦吗?
那你不如写一个脚本,直接让他运行两个呢?
x3e5 发表于 2024-6-24 09:05
[Python] 纯文本查看 复制代码
import os
import shutil
import hashlib
from datetime import datetime
import tkinter as tk
from tkinter import filedialog

def get_week_and_year(mtime):
    """根据修改时间获取年份和周数"""
    date = datetime.fromtimestamp(mtime)
    year = date.year
    week = date.isocalendar()[1]  # 使用isocalendar获取周数
    return year, week

def get_md5_checksum(path):
    """获取文件或文件夹的MD5哈希值"""
    if os.path.isfile(path):
        hash_md5 = hashlib.md5()
        with open(path, "rb") as f:
            for chunk in iter(lambda: f.read(4096), b""):
                hash_md5.update(chunk)
        return hash_md5.hexdigest()
    else:
        # 这里我们使用文件夹内所有文件的MD5来生成文件夹的哈希值
        folder_hash = hashlib.md5()
        for dirpath, _, filenames in os.walk(path):
            for filename in filenames:
                file_path = os.path.join(dirpath, filename)
                with open(file_path, "rb") as f:
                    for chunk in iter(lambda: f.read(4096), b""):
                        folder_hash.update(chunk)
        return folder_hash.hexdigest()

def organize_items_by_date(source_dir, dest_dir, is_file):
    """按照修改日期组织文件和文件夹,并处理同名文件的md5冲突"""
    if not os.path.exists(dest_dir):
        os.makedirs(dest_dir)

    for item in os.listdir(source_dir):
        item_path = os.path.join(source_dir, item)
        if (is_file and os.path.isfile(item_path)) or (not is_file and os.path.isdir(item_path)):
            mtime = os.path.getmtime(item_path)
            year, week = get_week_and_year(mtime)
            dest_base_path = os.path.join(dest_dir, str(year), f"周{week}")

            if not os.path.exists(dest_base_path):
                os.makedirs(dest_base_path)

            dest_item_path = os.path.join(dest_base_path, item)
            if os.path.exists(dest_item_path):
                # 如果目标文件或文件夹已存在,比较MD5
                dest_md5 = get_md5_checksum(dest_item_path)
                source_md5 = get_md5_checksum(item_path)
                if dest_md5 == source_md5:
                    print(f"Skipping {item_path} because it has the same MD5 as {dest_item_path}.")
                    continue
                else:
                    # MD5不同,选择重命名
                    base, ext = os.path.splitext(item)
                    counter = 1
                    while os.path.exists(dest_item_path):
                        if is_file:
                            new_item = f"{base}_{counter}{ext}"
                        else:
                            new_item = f"{base}_{counter}"
                        dest_item_path = os.path.join(dest_base_path, new_item)
                        counter += 1
            shutil.move(item_path, dest_item_path)
            print(f"Moved {item_path} to {dest_item_path}")

def select_and_organize(is_file):
    root = tk.Tk()
    root.withdraw()  # 隐藏主窗口
    source_directory = filedialog.askdirectory(title="请选择待整理的文件夹")
    destination_directory = filedialog.askdirectory(title="请选择目标文件夹")
    if source_directory and destination_directory:
        organize_items_by_date(source_directory, destination_directory, is_file)
    else:
        print("未选择文件夹或目标文件夹")

# 选择要整理的类型:文件或文件夹
select_and_organize(is_file=False)  # 整理文件夹
select_and_organize(is_file=True)   # 整理文件


优化点包括:
  • 合并了两个get_week_and_year函数,使用datetime.isocalendar()来获取周数,这比strftime('%V')更直接。
  • 合并了MD5哈希值获取的逻辑,现在get_md5_checksum可以处理文件和文件夹。
  • 重构了organize_items_by_date函数,使其可以同时处理文件和文件夹,通过is_file参数来区分。
  • 添加了select_and_organize函数,用于选择文件夹和目标文件夹,并根据is_file参数调用organize_items_by_date。
  • 移除了不必要的print语句和变量,使代码更加简洁。
这段代码仍然需要在具有图形界面的环境中运行。如果你希望从命令行运行,可以取消注释并修改源文件夹和目标文件夹的输入方式
 楼主| llyaomo 发表于 2024-6-24 10:18
x3e5 发表于 2024-6-24 09:05
[mw_shl_code=python,true]import os
import shutil
import hashlib

这个代码选择了四次文件夹路径,这个就没必要了呀。请大佬帮我改下,功能合二为一后,文件夹的需求只需要选两次就好,感谢!
 楼主| llyaomo 发表于 2024-6-24 10:31
莫谷 发表于 2024-6-24 08:39
为啥非得合并呢?你是觉得运行两次够麻烦吗?
那你不如写一个脚本,直接让他运行两个呢?

就是嫌麻烦呀。PS,我开头说的很清楚啦,是用AI生成的代码,我不会PY,只能根据生成的代码,修改一些边边角角的地方,例如文件夹的选取,从脚本里的固定路径输入改成UI界面的选取,创建文件夹的命名从6月改成06月,这些都是我从几段AI代码里对比出来,然后自己生搬硬套的。再多的就不会了
x3e5 发表于 2024-6-24 10:50
llyaomo 发表于 2024-6-24 10:18
这个代码选择了四次文件夹路径,这个就没必要了呀。请大佬帮我改下,功能合二为一后,文件夹的需求只需要 ...

[Python] 纯文本查看 复制代码
import os
import shutil
import hashlib
from datetime import datetime
import tkinter as tk
from tkinter import filedialog

# 根据文件或文件夹的最后修改时间获取年份和周数
def get_week_and_year(mtime):
    date = datetime.fromtimestamp(mtime)  # 将时间戳转换为日期
    year = date.year  # 获取年份
    week = date.isocalendar()[1]  # 获取ISO周数
    return year, week

# 计算文件或文件夹的MD5哈希值
def get_md5_checksum(path):
    if os.path.isfile(path):  # 如果是文件
        hash_md5 = hashlib.md5()
        with open(path, "rb") as f:
            for chunk in iter(lambda: f.read(4096), b""):  # 读取文件分块
                hash_md5.update(chunk)
        return hash_md5.hexdigest()  # 返回MD5哈希值
    else:  # 如果是文件夹
        folder_hash = hashlib.md5()
        for dirpath, _, filenames in os.walk(path):  # 遍历文件夹
            for filename in filenames:
                file_path = os.path.join(dirpath, filename)
                with open(file_path, "rb") as f:
                    for chunk in iter(lambda: f.read(4096), b""):
                        folder_hash.update(chunk)
        return folder_hash.hexdigest()

# 选择文件夹的函数,返回用户选择的目录路径
def select_directory(title):
    root = tk.Tk()
    root.withdraw()  # 隐藏主窗口
    directory = filedialog.askdirectory(title=title)  # 弹出选择文件夹的对话框
    return directory

# 按照修改日期组织文件和文件夹,并处理同名文件的md5冲突
def organize_items_by_date(source_dir, dest_dir, is_file):
    if not os.path.exists(dest_dir):
        os.makedirs(dest_dir)  # 如果目标目录不存在,则创建

    for item in os.listdir(source_dir):  # 遍历源目录中的所有项
        item_path = os.path.join(source_dir, item)
        if (is_file and os.path.isfile(item_path)) or (not is_file and os.path.isdir(item_path)):
            mtime = os.path.getmtime(item_path)  # 获取最后修改时间
            year, week = get_week_and_year(mtime)
            dest_base_path = os.path.join(dest_dir, str(year), f"周{week}")  # 确定目标路径

            if not os.path.exists(dest_base_path):
                os.makedirs(dest_base_path)  # 如果目标路径不存在,则创建

            dest_item_path = os.path.join(dest_base_path, item)  # 确定目标项的完整路径
            if os.path.exists(dest_item_path):  # 如果目标项已存在
                dest_md5 = get_md5_checksum(dest_item_path)  # 获取目标项的MD5
                source_md5 = get_md5_checksum(item_path)  # 获取源项的MD5
                if dest_md5 == source_md5:  # 如果MD5相同,则跳过
                    print(f"Skipping {item_path} because it has the same MD5 as {dest_item_path}.")
                    continue
                else:  # 如果MD5不同,则重命名
                    base, ext = os.path.splitext(item)
                    counter = 1
                    while os.path.exists(dest_item_path):
                        if is_file:
                            new_item = f"{base}_{counter}{ext}"
                        else:
                            new_item = f"{base}_{counter}"
                        dest_item_path = os.path.join(dest_base_path, new_item)
                        counter += 1
            shutil.move(item_path, dest_item_path)  # 移动文件或文件夹
            print(f"Moved {item_path} to {dest_item_path}")

# 选择要整理的类型:文件或文件夹,并执行整理
def select_and_organize(is_file):
    source_directory = select_directory("请选择待整理的文件夹")  # 选择源文件夹
    destination_directory = select_directory("请选择目标文件夹")  # 选择目标文件夹
    if source_directory and destination_directory:  # 如果两个目录都已选择
        organize_items_by_date(source_directory, destination_directory, is_file)  # 执行整理
    else:
        print("未选择文件夹或目标文件夹")

# 运行程序,整理文件夹
select_and_organize(is_file=False)
# 运行程序,整理文件
select_and_organize(is_file=True)
 楼主| llyaomo 发表于 2024-6-24 11:13
x3e5 发表于 2024-6-24 10:50
[mw_shl_code=python,true]import os
import shutil
import hashlib

大佬你没能理解我的意思,你这个新代码,还是选择了四次文件夹。步骤1选了两次,步骤二选了两次。我需要将步骤1和2的文件夹选取也合并

# 步骤1
select_and_organize(is_file=False)

# 步骤2

select_and_organize(is_file=True)

x3e5 发表于 2024-6-24 13:29
llyaomo 发表于 2024-6-24 11:13
大佬你没能理解我的意思,你这个新代码,还是选择了四次文件夹。步骤1选了两次,步骤二选了两次。我需要 ...

这样?

[Python] 纯文本查看 复制代码
# 以上内容不变
def select_and_organize(organize_type):
    root = tk.Tk()
    root.withdraw()  # 隐藏主窗口
    source_directory = filedialog.askdirectory(title="请选择待整理的文件夹")
    
    if not source_directory:
        print("未选择文件夹")
        return
    
    organize_files = organize_type == 'files'
    destination_directory = source_directory if organize_files else filedialog.askdirectory(title="请选择目标文件夹")
    
    if destination_directory:
        organize_items_by_date(source_directory, destination_directory, organize_files)
    else:
        print("未选择目标文件夹")

# 运行程序,整理文件夹和文件
select_and_organize('folders')  # 整理文件夹
select_and_organize('files')    # 整理文件
 楼主| llyaomo 发表于 2024-6-24 16:02
x3e5 发表于 2024-6-24 13:29
这样?

[mw_shl_code=python,true]

这一段逻辑还是有问题,处理文件的时候,仍然需要选取文件夹,且文件对应的source_dir和dest_dir,变的一样了。
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-12-15 16:39

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表