吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 6196|回复: 64
收起左侧

[原创工具] [完全开源]解决你大部分文件移动需求的实用工具

  [复制链接]
鸠山一茶 发表于 2024-2-27 18:02

由于楼主平时遇到过很多的文件需要移动,但是手动操作太麻烦了,于是楼主开发了移动-文件夹综合工具这款工具,下面是程序运行界面:

程序运行界面

本项目涵盖了大部分移动文件夹需要的功能,并且为了测试这个程序开发了下面的第二款程序,伪文件生成的程序,下面的程序可以帮助程序开发者生成需要的伪文件来进行测试,下面是运行界面:

伪文件生成工具界面

这两款小工具均开放源代码,下面首先提供程序的编译本体

移动-文件夹综合工具

伪文件生成器

下面是代码

import os
import shutil
from concurrent.futures import ThreadPoolExecutor
from datetime import datetime

from rich.console import Console
from rich.markdown import Markdown
from rich.panel import Panel
from rich.progress import track
from rich.prompt import Prompt
from rich.text import Text
from rich.traceback import install

install()
console = Console()

GITHUB_URL = "https://gist.github.com/Hellohistory/54b529cfc4d53c3041f3d005785a8e77"
AUTHOR_NAME = "Hellohistory"

def display_script_info():
    """显示脚本信息"""
    header_markdown = Markdown(
        f"# 文件整理工具\n\n👤 作者: {AUTHOR_NAME}\n🔗 GitHub: [链接]({GITHUB_URL})\n\n[脚本信息] 这是一个用于文件整理的脚本,包括文件移动、文件夹重命名等功能。")
    console.print(Panel(header_markdown, title="[bold magenta]欢迎[/bold magenta]", expand=False, border_style="red"))

def display_footer():
    """显示程序尾部信息"""
    footer_text = Text.assemble(
        ("脚本由 ", "bold"),
        (AUTHOR_NAME, "bold green"),
        (" 编写 - ", "bold"),
        ("GitHub", "link " + GITHUB_URL),
        style="italic"
    )
    console.print(Panel(footer_text, style="green"))

def handle_duplicate_file(dest_file):
    """处理目标文件夹中的同名文件"""
    base, extension = os.path.splitext(dest_file)
    timestamp = datetime.now().strftime("%Y%m%d%H%M%S")
    new_dest_file = f"{base}_{timestamp}{extension}"
    return new_dest_file

def move_file(src_file, dest_file):
    try:
        shutil.move(src_file, dest_file)
        console.log(f"文件 {src_file} 已移动到 {dest_file}")
    except Exception as e:
        console.log(f"无法移动文件 {src_file}: {e}")

def move_files():
    """移动文件的功能实现"""
    src_dir = Prompt.ask("请输入源文件夹路径", console=console)
    dest_dir = Prompt.ask("请输入目标文件夹路径", console=console)

    src_dir = os.path.abspath(src_dir)
    dest_dir = os.path.abspath(dest_dir)
    file_tasks = []

    for root, _, files in os.walk(src_dir):
        for name in files:
            src_file = os.path.join(root, name)
            dest_file = os.path.join(dest_dir, name)
            if os.path.exists(dest_file):
                dest_file = handle_duplicate_file(dest_file)
            file_tasks.append((src_file, dest_file))

    with ThreadPoolExecutor(max_workers=5) as executor:
        for src_file, dest_file in file_tasks:
            executor.submit(move_file, src_file, dest_file)

def rename_folders():
    """重命名文件夹的功能实现,去掉'_'和后续数字"""
    base_dir = Prompt.ask("请输入文件夹所在的基本路径", console=console)
    start_number_str = Prompt.ask("请输入文件夹编号起始数字", default="100", console=console)
    start_number = int(start_number_str)

    folders = [d for d in os.listdir(base_dir) if os.path.isdir(os.path.join(base_dir, d))]
    for folder_name in track(sorted(folders), description="正在重命名文件夹..."):
        old_path = os.path.join(base_dir, folder_name)
        new_folder_name = f"{start_number:03d}"  # 去掉'_'和后续数字
        new_path = os.path.join(base_dir, new_folder_name)
        os.rename(old_path, new_path)
        console.log(f"文件夹 {old_path} 重命名为 {new_path}")
        start_number += 1

def select_log_level():
    """选择日志级别"""
    level = Prompt.ask("请选择日志级别 (1-简单, 2-详细)", choices=["1", "2"], default="1", console=console)
    if level == "1":
        console.log("已设置为简单日志级别")
    else:
        console.log("已设置为详细日志级别")

def backup_file(src_file, dest_file):
    try:
        shutil.copy2(src_file, dest_file)
        console.log(f"文件 {src_file} 已备份到 {dest_file}")
    except Exception as e:
        console.log(f"无法备份文件 {src_file}: {e}")

def backup_files():
    """备份文件的功能实现"""
    src_dir = Prompt.ask("请输入需要备份的源文件夹路径", console=console)
    dest_dir = Prompt.ask("请输入备份文件的目标文件夹路径", console=console)

    src_dir = os.path.abspath(src_dir)
    dest_dir = os.path.abspath(dest_dir)

    if not os.path.exists(dest_dir):
        os.makedirs(dest_dir)
        console.log(f"已创建备份目标文件夹 {dest_dir}")

    file_tasks = []

    for root, _, files in os.walk(src_dir):
        for name in files:
            src_file = os.path.join(root, name)
            dest_file = os.path.join(dest_dir, name)
            if os.path.exists(dest_file):
                dest_file = handle_duplicate_file(dest_file)
            file_tasks.append((src_file, dest_file))

    with ThreadPoolExecutor(max_workers=5) as executor:
        for src_file, dest_file in file_tasks:
            executor.submit(backup_file, src_file, dest_file)

def move_subfolder_files_to_parent():
    """将子文件夹内的文件移动到父文件夹"""
    parent_dir = Prompt.ask("请输入父文件夹路径", console=console)
    parent_dir = os.path.abspath(parent_dir)

    if not os.path.isdir(parent_dir):
        console.log(f"指定的路径不是一个文件夹: {parent_dir}")
        return

    file_tasks = []

    subfolders = [d for d in os.listdir(parent_dir) if os.path.isdir(os.path.join(parent_dir, d))]
    for folder in subfolders:
        folder_path = os.path.join(parent_dir, folder)
        for root, _, files in os.walk(folder_path):
            for name in files:
                src_file = os.path.join(root, name)
                dest_file = os.path.join(parent_dir, name)
                if os.path.exists(dest_file):
                    dest_file = handle_duplicate_file(dest_file)
                file_tasks.append((src_file, dest_file))

    with ThreadPoolExecutor(max_workers=5) as executor:
        for src_file, dest_file in file_tasks:
            executor.submit(move_file, src_file, dest_file)

def split_folder(folder_path, subfolder_count):
    """将文件夹中的文件均匀分配到指定数量的子文件夹中"""
    files = [f for f in os.listdir(folder_path) if os.path.isfile(os.path.join(folder_path, f))]
    total_files = len(files)
    files_per_subfolder, remainder = divmod(total_files, subfolder_count)

    current_file_index = 0
    for i in range(subfolder_count):
        subfolder_path = os.path.join(folder_path, f"{i + 1}")
        os.makedirs(subfolder_path, exist_ok=True)
        for j in range(files_per_subfolder + (1 if i < remainder else 0)):
            shutil.move(os.path.join(folder_path, files[current_file_index]), subfolder_path)
            current_file_index += 1
    console.log("文件移动完成!")

def move_all_files(source_folder, destination_folder):
    """将源文件夹中的所有文件移动到目标文件夹,包括子文件夹中的文件"""
    files = os.listdir(source_folder)
    for filename in files:
        file_path = os.path.join(source_folder, filename)
        if os.path.isfile(file_path):
            shutil.move(file_path, destination_folder)
        elif os.path.isdir(file_path):
            move_all_files(file_path, destination_folder)
    console.log("文件移动完成!")

def main():
    display_script_info()
    console.print("文件整理工具", style="bold green")

    menu_options = {
        "1": ("移动文件", move_files),
        "2": ("重命名文件夹", rename_folders),
        "3": ("选择日志级别", select_log_level),
        "4": ("备份文件", backup_files),
        "5": ("将子文件夹内的文件移动到父文件夹", move_subfolder_files_to_parent),
        "6": ("文件夹中文件平均分配到子文件夹", lambda: split_folder_prompt()),
        "7": ("移动源文件夹中的所有文件到目标文件夹", lambda: move_all_files_prompt())
    }

    while True:
        console.print(Panel("[bold yellow]菜单选项[/bold yellow]", expand=False))
        for key, (desc, _) in menu_options.items():
            console.print(Text.assemble((f"{key}: ", "bold cyan"), (desc, "bold white")))
        console.print("0: 退出", style="bold red")

        choice = Prompt.ask("请选择一个选项", choices=list(menu_options.keys()) + ["0"], console=console)
        if choice == "0":
            break
        else:
            func = menu_options[choice][1]
            func()

    display_footer()

def split_folder_prompt():
    folder_path = Prompt.ask("请输入需要分配的文件夹路径", console=console)
    subfolder_count = int(Prompt.ask("请输入子文件夹数量", console=console))
    split_folder(folder_path, subfolder_count)

def move_all_files_prompt():
    source_folder = Prompt.ask("请输入源文件夹路径", console=console)
    destination_folder = Prompt.ask("请输入目标文件夹路径", console=console)
    move_all_files(source_folder, destination_folder)

if __name__ == "__main__":
    main()
import os
import random
from rich.console import Console
from rich.table import Table
from rich.progress import track

def display_intro():
    table = Table(title="程序介绍")

    table.add_column("项目", justify="right", style="cyan", no_wrap=True)
    table.add_column("信息(按下Ctrl后点击链接访问)", style="magenta")

    table.add_row("程序名称", "伪文件生成")
    table.add_row("开发者", "Hellohistory")
    table.add_row("项目源码(Github)", "https://gist.github.com/Hellohistory/d38ebe4730a2235f40a465652090145b")
    table.add_row("更多项目(Github)", "https://github.com/Hellohistory/OpenPrepTools")
    table.add_row("更多项目(Gitee)", "https://gitee.com/Hellohistory/OpenPrepTools")

    console.print(table)

def generate_random_name(base_text, max_length, existing_names):
    while True:
        random_name = ''.join(random.choice(base_text) for _ in range(random.randint(1, max_length)))
        if random_name not in existing_names:
            return random_name

def create_fake_files(directory, file_details, use_random_names=False, base_text="", max_length=10):
    if not os.path.exists(directory):
        os.makedirs(directory)

    total_files = sum(file_details.values())
    existing_names = set()

    for ext, num_files in file_details.items():
        for i in track(range(num_files), description=f"正在创建 .{ext} 文件..."):
            if use_random_names:
                random_name = generate_random_name(base_text, max_length, existing_names)
                filename = f"{random_name}.{ext}"
                existing_names.add(random_name)
            else:
                filename = f"fake_file_{i + 1}.{ext}"
            filepath = os.path.join(directory, filename)
            with open(filepath, 'w') as f:
                f.write("This is a fake file.")
    console.print(f"[green]{total_files} 个伪文件已成功创建在 {directory} 中。[/green]")

if __name__ == "__main__":
    console = Console()
    display_intro()

    while True:
        directory = console.input("请输入要创建文件的目录路径:")
        use_random_names = console.input("是否使用随机文件名?(y/n):").lower() == 'y'
        base_text = ""
        max_length = 10
        if use_random_names:
            base_text = console.input("请输入用于生成文件名的文字:")
            max_length = int(console.input("请输入文件名的最大长度:"))

        extensions_input = console.input("请输入文件的扩展名(用逗号分隔):")
        if extensions_input.strip() == "":
            file_details = {"txt": 1000}
        else:
            extensions = [ext.strip() for ext in extensions_input.replace(",", ",").split(",")]
            file_details = {}
            for ext in extensions:
                num_input = console.input(f"请输入要为 .{ext} 文件创建的数量[默认为1000]:")
                num_files = int(num_input) if num_input.strip() != "" else 1000
                file_details[ext] = num_files

        create_fake_files(directory, file_details, use_random_names, base_text, max_length)

        continue_choice = console.input("是否继续创建文件?(y/n):")
        if continue_choice.lower() != "y":
            console.print("[bold magenta]程序已退出。[/bold magenta]")
            break

免费评分

参与人数 14吾爱币 +19 热心值 +13 收起 理由
tiantianxiaoxue + 1 + 1 我很赞同!
littley520 + 1 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
renshu16 + 1 + 1 谢谢@Thanks!
open88 + 1 + 1 谢谢@Thanks!
jiutianjun + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
caihuachaorou87 + 1 + 1 谢谢@Thanks!
Zatoichi + 1 + 1 谢谢@Thanks!
我love破戒 + 1 + 1 热心回复!
虚空之承 + 1 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
LYTLYT + 1 + 1 谢谢@Thanks!
schtg + 1 + 1 谢谢@Thanks!
yanglinman + 1 谢谢@Thanks!
远水涵秋 + 1 + 1 我很赞同!
风之暇想 + 7 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!

查看全部评分

本帖被以下淘专辑推荐:

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

无言之城 发表于 2024-2-28 09:13
大量文件移动推荐fastcopy类专业文件复制软件,或者goodsync类同步软件
jiajia007 发表于 2024-2-28 09:29
dxmcf 发表于 2024-2-27 18:19
LKHT666 发表于 2024-2-27 18:24
谢谢楼主分享,实用的工具
sai609 发表于 2024-2-27 18:34

U盘插入a电脑win后,此前导入的文档资料(文件夹还在)全部消失不见,但显示占容内存,
即使取消隐藏文件夹功能、火绒和360杀毒无异常、格式化,也是如此
u盘插入b电脑win后,实施上述操作(取消隐藏文件夹功能、360杀毒无异常)也是同样问题
u盘插入b电脑win后,格式化后再导入资料是ok
但u盘放到a电脑win后能看到资料,当a电脑导入资料就又出现同样问题
so该咋办呢?
 楼主| 鸠山一茶 发表于 2024-2-27 18:39
sai609 发表于 2024-2-27 18:34
U盘插入a电脑win后,此前导入的文档资料(文件夹还在)全部消失不见,但显示占容内存,
即使取消隐藏文 ...

啊这,Windows版本是多少,文件数量是多少,操作过程当中程序是否出现报错等情况,我需要复现一下再告诉您问题出在哪里
lxchk0000 发表于 2024-2-27 18:45
感谢分享
sai609 发表于 2024-2-27 19:09
鸠山一茶 发表于 2024-2-27 18:39
啊这,Windows版本是多少,文件数量是多少,操作过程当中程序是否出现报错等情况,我需要复现一下再告诉 ...

win10,文件数量几十万,单个文件几十k,总量三g,将本地文件复制粘贴至u盘,只有文件夹,文件消失不见,隐藏功能已取消,360和火绒均查杀无异常
wlzxwfk 发表于 2024-2-27 19:11
谢谢楼主分享,很实用的工具!
 楼主| 鸠山一茶 发表于 2024-2-27 19:12
sai609 发表于 2024-2-27 19:09
win10,文件数量几十万,单个文件几十k,总量三g,将本地文件复制粘贴至u盘,只有文件夹,文件消失不见, ...

选择的哪种模式
头像被屏蔽
moruye 发表于 2024-2-27 21:04
提示: 作者被禁止或删除 内容自动屏蔽
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

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

GMT+8, 2024-11-21 19:11

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

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