鱼C论坛

 找回密码
 立即注册
查看: 2708|回复: 11

[已解决]通过python备份文件路径和文件名太长的问题!!

[复制链接]
发表于 2023-3-2 09:57:23 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
我在弄一个文件备份的程序
但是发现,
明明已经获取到了这个文件路径和文件名
却提示找不到这个文件()
# FileNotFoundError: [Errno 2] No such file or directory: 'E:\\...............\........\.........docx
原因可能是
太长的文件路径和文件名
在网上找了些资料,

一种说法就是在路径前加\\?\
没有试验成功
src = u'\\\\?\\' + src
dst = u'\\\\?\\' + dst

FileNotFoundError: [WinError 3] 系统找不到指定的路径。: '\\\\?\\...............\........\.........docx'

另一种说改注册表
也没有试验成功
# import winreg
# winreg.SetValueEx(winreg.CreateKey(winreg.HKEY_LOCAL_MACHINE, r'SYSTEMCurrentControlSetControlFileSystem'),
#                 'LongPathsEnabled', None, winreg.REG_DWORD, 1)


winreg.SetValueEx(winreg.CreateKey(winreg.HKEY_LOCAL_MACHINE, r'SYSTEMCurrentControlSetControlFileSystem'),
OSError: [WinError 87] 参数错误。

还有一种是通过处理路径长度
也没有试验成功
#import win32api
# path = win32api.GetShortPathName(path)

没有这个模块
安装不了

请教下大神们,也可以互相探讨,谢谢!!
最佳答案
2023-3-2 11:53:02
Windows 文件系统 NTFS 的文件名和目录路径有最大长度,即 MAX_PATH 限制最长 260 个字符

在 Windows 上,你可以尝试以下几种方法来解决这个问题:

1、使用相对路径:如果可能的话,尽量使用相对路径来引用文件。相对路径相对于当前工作目录或脚本文件所在目录。

2、使用短路径名:你可以使用 Python 中的 ctypes 模块来获取文件的短路径名。例如:
import ctypes
def short_path_name(long_name):
    """
    获取文件的短路径名
    """
    buf = ctypes.create_unicode_buffer(1024)
    ctypes.windll.kernel32.GetShortPathNameW(long_name, buf, len(buf))
    return buf.value
然后可以像这样使用:
src = short_path_name(src)
dst = short_path_name(dst)

3、使用 UNC 路径:UNC 路径的格式为 \\server\share\path\file,

它们不受文件路径长度限制的影响。如果你可以访问远程计算机或网络共享,可以使用 UNC 路径。

例如,如果你要备份的文件位于 E:\path\to\file.docx,你可以将其转换为 \\localhost\E$\path\to\file.docx。
src = r'\\localhost\E$\path\to\file.docx'
dst = r'\\localhost\E$\backup\file.docx'

4、你可以尝试使用本地组策略编辑器来启用长路径支持。

找到并打开文件(本地组策略编辑器)gpedit.msc,然后依次点开 计算机配置 > 管理模板 > 系统 > 文件系统,

找到“启用 Win32 长路径”,将其状态更改为“已启用”
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2023-3-2 10:07:20 From FishC Mobile | 显示全部楼层
随便发一个路径,大家看看
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2023-3-2 10:19:53 | 显示全部楼层
我帮你测试了一下,windows是有文件名长度限制的  估计是255
我测试路径长度 最大值是243  再长就不认了
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2023-3-2 10:59:44 | 显示全部楼层
wp231957 发表于 2023-3-2 10:19
我帮你测试了一下,windows是有文件名长度限制的  估计是255
我测试路径长度 最大值是243  再长就不认了

我刚刚做了个测试,以下这样子是可以
shutil.copy(f'{src}\{file}', dst)
src = '\\\\?\\E:.......
file = ‘  ’
dst = '\\\\?\\Z:........
shutil.copy(f'{src}\{file}', dst)

但是放在以下程序中就不行:
# -*- coding:utf-8 -*-
import os
import shutil
import time


# 文件备份函数
def copy_data(file, src, dst):
    shutil.copy(f'\\\\?\\{src}\{file}', dst)      # 这里添加后,我单独测试是可以的,
    # print(f'完成数据备份:{src}\{file}')


# 文件夹备份函数
def new_fold(file, src, dst):
    os.mkdir(f'{dst}/{file}')
    backup(src=f'{src}/{file}', dst=f'{dst}/{file}')


# 已备份文件夹子节点检查函数
def exist_fold(file, src, dst):
    src = f'{src}/{file}'
    dst = f'{dst}/{file}'
    src_file_name2 = os.listdir(src)
    for file2 in src_file_name2:
        if os.path.isdir(f'{src}/{file2}'):
            if not os.path.exists(f'{dst}/{file2}'):
                new_fold(file=file2, src=src, dst=dst)
            else:
                exist_fold(file=file2, src=src, dst=dst)
        else:
            if not os.path.exists(f'{dst}/{file2}'):
                copy_data(file=file2, src=src, dst=dst)


# 备份路径文件/文件夹差异比对函数
def backup(src, dst):
    """
    :param src: 原始路径
    :param dst: 备份路径
    """
    # 获取需备份文件夹中所有文件和文件夹
    src_file_name = os.listdir(src)
    for file in src_file_name:
        if os.path.isdir(f'{src}{file}'):
            if not os.path.exists(f'{dst}/{file}'):

                new_fold(file=file, src=src, dst=dst)
            else:

                exist_fold(file=file, src=src, dst=dst)
        else:
            if not os.path.exists(f'{dst}/{file}'):

                copy_data(file=file, src=src, dst=dst)


# 调用主函数
if __name__ == '__main__':
    src = input(r'请输入原始数据路径(eg.C:\backup):')
    dst = input(r'请输入备份数据路径(eg.C:\backup):')

    threshold = input('请输入备份时间间隔(min):')
    i = 0
    while True:
        i += 1
        print(f'===============正在进行第{i}次备份===============')

        backup(src=src, dst=dst)
        # print('完成备份')
        time.sleep(int(threshold) * 60)

想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2023-3-2 11:53:02 | 显示全部楼层    本楼为最佳答案   
Windows 文件系统 NTFS 的文件名和目录路径有最大长度,即 MAX_PATH 限制最长 260 个字符

在 Windows 上,你可以尝试以下几种方法来解决这个问题:

1、使用相对路径:如果可能的话,尽量使用相对路径来引用文件。相对路径相对于当前工作目录或脚本文件所在目录。

2、使用短路径名:你可以使用 Python 中的 ctypes 模块来获取文件的短路径名。例如:
import ctypes
def short_path_name(long_name):
    """
    获取文件的短路径名
    """
    buf = ctypes.create_unicode_buffer(1024)
    ctypes.windll.kernel32.GetShortPathNameW(long_name, buf, len(buf))
    return buf.value
然后可以像这样使用:
src = short_path_name(src)
dst = short_path_name(dst)

3、使用 UNC 路径:UNC 路径的格式为 \\server\share\path\file,

它们不受文件路径长度限制的影响。如果你可以访问远程计算机或网络共享,可以使用 UNC 路径。

例如,如果你要备份的文件位于 E:\path\to\file.docx,你可以将其转换为 \\localhost\E$\path\to\file.docx。
src = r'\\localhost\E$\path\to\file.docx'
dst = r'\\localhost\E$\backup\file.docx'

4、你可以尝试使用本地组策略编辑器来启用长路径支持。

找到并打开文件(本地组策略编辑器)gpedit.msc,然后依次点开 计算机配置 > 管理模板 > 系统 > 文件系统,

找到“启用 Win32 长路径”,将其状态更改为“已启用”
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2023-3-2 13:03:53 | 显示全部楼层
isdkz 发表于 2023-3-2 11:53
Windows 文件系统 NTFS 的文件名和目录路径有最大长度,即 MAX_PATH 限制最长 260 个字符

在 Windows 上 ...


我发现问题,因为程序执行的是‘/’路径,但我用了加长路径识别,要用‘\‘路径
我现在想在最后一步
把地址中的‘/’全部替换成‘\’
但是发现‘\’这样子,ptyhon识别出转义符了,
有没有好的办法,把‘\’弄成字符呢?
感谢万分!!!
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2023-3-2 13:07:03 | 显示全部楼层
pysunred 发表于 2023-3-2 13:03
我发现问题,因为程序执行的是‘/’路径,但我用了加长路径识别,要用‘\‘路径
我现在想在最后一步
...

在字符串前面加个 r 就行

比如:
src = r"d:\temp"
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2023-3-2 13:18:27 | 显示全部楼层
isdkz 发表于 2023-3-2 13:07
在字符串前面加个 r 就行

比如:

刚刚测试了一下,这样子是可以,多加一个\
new_src = src.replace('/', '\\', 100)
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2023-3-2 13:20:06 | 显示全部楼层
pysunred 发表于 2023-3-2 13:18
刚刚测试了一下,这样子是可以,多加一个\
new_src = src.replace('/', '\\', 100)

这样确实可以,如果字符串的最后一个字符是 \ 就不能用 r,只能用 \\
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2023-3-2 14:29:48 | 显示全部楼层
isdkz 发表于 2023-3-2 13:20
这样确实可以,如果字符串的最后一个字符是 \ 就不能用 r,只能用 \\

用三引号啊
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2023-3-2 14:32:00 | 显示全部楼层
本帖最后由 isdkz 于 2023-3-2 14:34 编辑


三引号怎么用?你试试在字符串的最后一个字符是 \ 的时候用三引号看看
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2023-3-2 15:15:41 | 显示全部楼层
isdkz 发表于 2023-3-2 14:32
三引号怎么用?你试试在字符串的最后一个字符是 \ 的时候用三引号看看

呃,这个
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2025-1-2 01:41

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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