吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 2543|回复: 39
上一主题 下一主题
收起左侧

[Windows] 超级批量复制工具 V2.1【更新】

  [复制链接]
跳转到指定楼层
楼主
ziyuejun 发表于 2024-12-5 12:25 回帖奖励
本帖最后由 ziyuejun 于 2024-12-10 16:49 编辑

以下为更新后的V2.1版本

更新内容:
1、将Windows PowerShell语言更换为了适配性更好的Python语言;
2、将单线程处理任务模式,改为多线程处理模式;
3、增加是否保留原文件所在目录结构的功能,默认不保留;
4、新增支持xls、xlsx表格文档文件解析。

您的赞赏、评论是我更新下去的动力!


下载地址:
下载地址.txt (144 Bytes, 下载次数: 32)

软件运行截图:


附软件源码:
[Python] 纯文本查看 复制代码
import tkinter as tk  
from tkinter import filedialog, messagebox  
import os  
import shutil  
import chardet  
from concurrent.futures import ThreadPoolExecutor  
import time  
import pandas as pd  

def select_file_list():  
    file_path = filedialog.askopenfilename(filetypes=[("Text, CSV, and Excel Files", "*.txt *.csv *.xls *.xlsx ")])  
    if file_path:  
        global file_list_path  
        file_list_path = file_path  
        file_list_var.set(file_list_path)  


def detect_file_encoding(file_path, default='utf-8'):  
    """使用 chardet 检测文件的编码。  
    
    参数:  
        file_path (str): 要检测的文件的路径。  
        default (str): 当无法检测到编码时使用的默认编码。  

    返回:  
        str: 检测到的文件编码或默认编码。  
    """  
    with open(file_path, 'rb') as file:  
        raw_data = file.read(1024)  # 读取文件的头部以分析编码  
    result = chardet.detect(raw_data)  
    encoding = result['encoding']  
    return encoding if encoding else default


def read_file_names(file_list_path):  
    if file_list_path.endswith('.xlsx') or file_list_path.endswith('.xls'):  
        engine = 'xlrd' if file_list_path.endswith('.xls') else None  
        df = pd.read_excel(file_list_path, engine=engine)  
        file_names = df.iloc[:, 0].dropna().tolist()  # 假设文件名在第一列  
    else:  
        encoding = detect_file_encoding(file_list_path)  
        with open(file_list_path, 'r', encoding=encoding) as file:  
            file_names = [line.strip() for line in file if line.strip()]  

    return file_names 


def copy_file(src_file, target_dir, preserve_structure=False, base_dir=None):  
    """  
    复制文件到目标目录。  
    
    参数:  
        src_file (str): 源文件的完整路径。  
        target_dir (str): 目标目录。  
        preserve_structure (bool): 是否保留原始目录结构。  
        base_dir (str, optional): 如果保留目录结构,源目录的基本路径。  

    返回:  
        str: 如果复制成功,返回目标文件路径;否则返回 None。  
    """  
    try:  
        # 保留目录结构复制  
        if preserve_structure and base_dir:  
            # 计算相对于 base_dir 的相对路径  
            rel_path = os.path.relpath(os.path.dirname(src_file), base_dir)  
            target_path = os.path.join(target_dir, rel_path)  
        else:  
            # 不保留目录结构时,直接复制到目标目录  
            target_path = target_dir  

        # 确保目标目录存在  
        os.makedirs(target_path, exist_ok=True)  

        # 构建目标文件完整路径  
        target_file = os.path.join(target_path, os.path.basename(src_file))  

        # 执行文件复制  
        shutil.copy2(src_file, target_file)  

        return target_file  

    except Exception as e:  
        print(f"复制文件 {src_file} 时发生错误: {e}")  
        return None

def start_copying():  
    if not source_path or not file_list_path or not target_path:  
        messagebox.showerror("错误", "请先选择必需的路径和文件。")  
        return  

    preserve_structure = structure_var.get() == "Yes"  

    try:  
        file_names = read_file_names(file_list_path)  

        if not file_names:  
            messagebox.showerror("错误", "文件名列表为空或无有效条目。")  
            return  

        start_time = time.time()  
        copied_files_count = 0  

        max_workers = min(5, len(file_names)) if file_names else 1  
        with ThreadPoolExecutor(max_workers=max_workers) as executor:  
            futures = []  

            for file_name in file_names:  
                for root, _, files in os.walk(source_path):  
                    if file_name in files:  
                        src_file = os.path.join(root, file_name)  
                        futures.append(executor.submit(copy_file, src_file, target_path, preserve_structure, source_path))  

            for future in futures:  
                if future.result() is None:  
                    copied_files_count += 1  

        elapsed_time = time.time() - start_time  
        messagebox.showinfo("完成", f"文件复制完成!复制了 {copied_files_count} 个文件。用时 {elapsed_time:.2f} 秒。"  
                                    f"\n使用了 {max_workers} 个线程。")  

    except Exception as e:  
        messagebox.showerror("错误", f"在复制时发生错误: {str(e)}")  

# Rest of the code remains unchanged  

def select_source_folder():  
    global source_path  
    source_path = filedialog.askdirectory()  
    source_path_var.set(source_path)  

def select_target_folder():  
    global target_path  
    target_path = filedialog.askdirectory()  
    target_path_var.set(target_path)  

# Initialize paths  
source_path = ""  
file_list_path = ""  
target_path = ""  

app = tk.Tk()  
app.title("超级批量复制工具 by JamesChan V2.1")  
app.geometry("420x350")  

source_path_var = tk.StringVar()  
file_list_var = tk.StringVar()  
target_path_var = tk.StringVar()  

tk.Button(app, text="选择原始文件夹", command=select_source_folder).place(x=10, y=10, width=120, height=30)  
tk.Entry(app, textvariable=source_path_var, state='readonly').place(x=140, y=15, width=250, height=20)  

tk.Button(app, text="导入文件名", command=select_file_list).place(x=10, y=50, width=120, height=30)  
tk.Entry(app, textvariable=file_list_var, state='readonly').place(x=140, y=55, width=250, height=20)  

tk.Button(app, text="目标文件夹", command=select_target_folder).place(x=10, y=90, width=120, height=30)  
tk.Entry(app, textvariable=target_path_var, state='readonly').place(x=140, y=95, width=250, height=20)  

structure_var = tk.StringVar(value="No")  
tk.Label(app, text="是否保留目录结构:").place(x=10, y=130)  
tk.Radiobutton(app, text="是", variable=structure_var, value="Yes").place(x=140, y=130)  
tk.Radiobutton(app, text="否", variable=structure_var, value="No").place(x=200, y=130)  

tk.Button(app, text="开始复制", command=start_copying).place(x=10, y=170, width=120, height=30)  

app.mainloop()




以下为V1.0版本

一款以导入的文件名为查找依据,根据查询结果将查到的文件自动复制到目标文件夹的工具。

基于Windows PowerShell语言开发,使用gpt-4o写的代码,使用Invoke-PS2EXE工具打包,未签名未混淆,可自行解包DIY,后附代码。
本人非码农,业余选手,首次发帖,大神嘴下留德,不喜勿喷。

如果您愿意赞赏,我将不胜感激!

百度网盘下载地址见附件
超级批量复制工具下载链接.txt (140 Bytes, 下载次数: 47)

使用步骤:
1、双击运行“超级批量复制工具.exe”工具;
2、点击“选择原始文件夹”,选择要复制的文件所在文件夹,可选择父目录,工具会自动查找子目录内容;
3、点击“导入文件名”,选择要导入的文件名所在文件,支持txt和CVS格式,文件名每条一行,需包含尾缀
4、点击“目标文件夹”,选择要把复制的文件保存的位置;
5、点击“开始复制”,即开始根据文件名搜索文件,匹配后将文件复制到指定文件夹,复制完成后弹窗提示。




附powershell代码:
[PowerShell] 纯文本查看 复制代码
Add-Type -AssemblyName System.Windows.Forms  
Add-Type -AssemblyName System.Drawing  

# Create the main form  
$form = New-Object System.Windows.Forms.Form  
$form.Text = "超级批量复制工具 by JamesChan V1.1"  
$form.Size = New-Object System.Drawing.Size(420, 300)  
$form.StartPosition = "CenterScreen"  

# Initialize paths  
$global:sourcePath = ""  
$global:fileListPath = ""  
$global:targetPath = ""  

# Source folder button  
$sourceButton = New-Object System.Windows.Forms.Button  
$sourceButton.Location = New-Object System.Drawing.Point(10, 10)  
$sourceButton.Size = New-Object System.Drawing.Size(120, 30)  
$sourceButton.Text = "选择原始文件夹"  
$form.Controls.Add($sourceButton)  

$sourceTextBox = New-Object System.Windows.Forms.TextBox  
$sourceTextBox.Location = New-Object System.Drawing.Point(140, 15)  
$sourceTextBox.Size = New-Object System.Drawing.Size(250, 20)  
$sourceTextBox.ReadOnly = $true  
$form.Controls.Add($sourceTextBox)  

$sourceButton.Add_Click({  
    $folderBrowser = New-Object System.Windows.Forms.FolderBrowserDialog  
    if ($folderBrowser.ShowDialog() -eq [System.Windows.Forms.DialogResult]::OK) {  
        $global:sourcePath = $folderBrowser.SelectedPath  
        $sourceTextBox.Text = $global:sourcePath  
    }  
})  

# File list button  
$fileListButton = New-Object System.Windows.Forms.Button  
$fileListButton.Location = New-Object System.Drawing.Point(10, 50)  
$fileListButton.Size = New-Object System.Drawing.Size(120, 30)  
$fileListButton.Text = "导入文件名"  
$form.Controls.Add($fileListButton)  

$fileListTextBox = New-Object System.Windows.Forms.TextBox  
$fileListTextBox.Location = New-Object System.Drawing.Point(140, 55)  
$fileListTextBox.Size = New-Object System.Drawing.Size(250, 20)  
$fileListTextBox.ReadOnly = $true  
$form.Controls.Add($fileListTextBox)  

$fileListButton.Add_Click({  
    $fileBrowser = New-Object System.Windows.Forms.OpenFileDialog  
    $fileBrowser.Filter = "Text and CSV Files (*.txt;*.csv)|*.txt;*.csv"  
    if ($fileBrowser.ShowDialog() -eq [System.Windows.Forms.DialogResult]::OK) {  
        $global:fileListPath = $fileBrowser.FileName  
        $fileListTextBox.Text = $global:fileListPath  
    }  
})  

# Target folder button  
$targetButton = New-Object System.Windows.Forms.Button  
$targetButton.Location = New-Object System.Drawing.Point(10, 90)  
$targetButton.Size = New-Object System.Drawing.Size(120, 30)  
$targetButton.Text = "目标文件夹"  
$form.Controls.Add($targetButton)  

$targetTextBox = New-Object System.Windows.Forms.TextBox  
$targetTextBox.Location = New-Object System.Drawing.Point(140, 95)  
$targetTextBox.Size = New-Object System.Drawing.Size(250, 20)  
$targetTextBox.ReadOnly = $true  
$form.Controls.Add($targetTextBox)  

$targetButton.Add_Click({  
    $folderBrowser = New-Object System.Windows.Forms.FolderBrowserDialog  
    if ($folderBrowser.ShowDialog() -eq [System.Windows.Forms.DialogResult]::OK) {  
        $global:targetPath = $folderBrowser.SelectedPath  
        $targetTextBox.Text = $global:targetPath  
    }  
})  

# Start copying button  
$copyButton = New-Object System.Windows.Forms.Button  
$copyButton.Location = New-Object System.Drawing.Point(10, 130)  
$copyButton.Size = New-Object System.Drawing.Size(120, 30)  
$copyButton.Text = "开始复制"  
$form.Controls.Add($copyButton)  

$copyButton.Add_Click({  
    if (-not $global:sourcePath -or -not $global:fileListPath -or -not $global:targetPath) {  
        [System.Windows.Forms.MessageBox]::Show("请先选择必需的路径和文件。", "错误")  
        return  
    }  

    # Read the file names from the list  
    $fileNames = Get-Content -Path $global:fileListPath -Encoding UTF8 | Where-Object { $_.Trim() -ne "" }  

    if (-not $fileNames) {  
        [System.Windows.Forms.MessageBox]::Show("文件名列表为空或无有效条目。", "错误")  
        return  
    }  

    # Ensure target directory exists  
    if (-not (Test-Path $global:targetPath)) {  
        New-Item -ItemType Directory -Path $global:targetPath | Out-Null  
    }  

    # Copy files  
    foreach ($fileName in $fileNames) {  
        $fileName = $fileName.Trim()  
        $files = Get-ChildItem -Path $global:sourcePath -Recurse -File | Where-Object { $_.Name -eq $fileName }  
        if ($files) {  
            foreach ($file in $files) {  
                $destFile = Join-Path -Path $global:targetPath -ChildPath $file.Name  
                Copy-Item -Path $file.FullName -Destination $destFile -Force  
            }  
        }  
    }  

    [System.Windows.Forms.MessageBox]::Show("文件复制完成!")  
})  

# Show the form  
$form.Add_Shown({ $form.Activate() })  
[void]$form.ShowDialog()

免费评分

参与人数 3吾爱币 +3 热心值 +3 收起 理由
wwwww1986528 + 1 + 1 谢谢@Thanks!
vitrel + 1 + 1 谢谢@Thanks!
aps0432892 + 1 + 1 我很赞同!

查看全部评分

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

推荐
 楼主| ziyuejun 发表于 2024-12-9 10:56 |楼主
boyixiao 发表于 2024-12-9 10:52
用everything也很快呀

everything查找文件很快,但是查找后需要手动复制文件到另一个目录下,有点繁琐。可能是我不太会用,不清楚everything有没有自动查找复制的功能
推荐
旅行mark 发表于 2024-12-19 16:17
ziyuejun 发表于 2024-12-19 15:47
感谢支持!可否详细描述一下需求,我试试能不能满足

当前逻辑是只能选择一个父文件夹路径然后进行全盘遍历查找复制,我的需求是选择多个局域网路径进行遍历查找,例如当前只能选择C盘一个路径去查找匹配复制,我的需求是同时选择C盘,D盘,E盘这三个路径,因为我给出的文件名是分别在这三个文件夹下,所以只能选择一个路径的话对于我的需求就无法满足了,感谢楼主回复
沙发
penghao0910 发表于 2024-12-6 14:29
3#
aps0432892 发表于 2024-12-6 21:09
本帖最后由 aps0432892 于 2024-12-6 21:23 编辑

很实用的工具,下载试用,不过对于办公来说,普遍都是用xlsx文件方便吧,txt和csv用的少,
4#
vitrel 发表于 2024-12-7 08:06
应该会用到,先下载收藏。
很不错的辅助工具。
5#
dlyuan 发表于 2024-12-7 09:29
非常方便 感谢分享
6#
龙隐 发表于 2024-12-7 09:29
呵呵呵,这东西可厉害了!
7#
zhoupeng79 发表于 2024-12-7 09:32
谢谢分享,感觉应该会用到
8#
unimog8000 发表于 2024-12-8 17:56

谢谢分享
9#
alexwb 发表于 2024-12-8 22:19
powershell 对多线程支持不是很好,还不如换成python或引用robocopy呢
10#
 楼主| ziyuejun 发表于 2024-12-9 08:30 |楼主
alexwb 发表于 2024-12-8 22:19
powershell 对多线程支持不是很好,还不如换成python或引用robocopy呢

感谢建议,因为我一般都是用在<100文件数量级的查找复制,所以没有考虑多线程处理,下一步考虑换成Python多线程处理。
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

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

GMT+8, 2024-12-22 22:37

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

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