Python 备份文件夹结构

本贴最后更新于 1308 天前,其中的信息可能已经事过景迁
import sys
import os
import pathlib
import shutil
import filecmp
import fnmatch
import tqdm
from pprint import pprint

r'''
作者:HaujetZhao
日期:2021 年 1 月 24 日

脚本功能:
    将 “源目录” 的文件夹、文件结构复制到 “目标文件夹”,小于指定大小的文件复制过去,大于指定大小的文件,就不复制了,而是在目标文件夹中新建一个同名的空白文件。

解决的问题:

    硬盘上有许多珍贵的资料,是辛苦收集来的,它们有这些特征:

    * 它们不是太珍贵,因为在网上花一些力气可以找到
    * 它们也珍贵,因为的确有用
    * 某些时候可能需要其中一些文件
    * 其中有一些文件体积特别大,多处备份会很费空间、成本
    * 丢掉这些文件可能会有些 trouble
    * 一旦丢失,因为不记得都有哪些文件,即使网上有资源,也很难一下子收集起来

    比如:

    * 一些电影、记录片(动辄好几十 GB)
    * 为了防止和谐、方便观看而缓存的一些油管、B站的优秀视频(动辄好几百 MB)
    * 一些百科文件(动辄好几十 GB)

    它们不值得花大精力进行冗余备份,但是一旦丢掉也挺可惜。

    所以,我就需要将这些文件夹、文件名的结构备份下来,备份占用的体积小,同时,在源文件丢失后,我可以清楚地知道有哪些文件丢了,再去网上下一份。

    另外,还加了一个筛选功能,比如,小于 1000kB 的文件就备份上,这些文件一般是文本文件,里面的信息一般比较重要。

    比如,可以在一个文本文件中中记录下,某些视频是从哪里下载来的,链接是什么,UP 主是谁。这样,文件丢失后,还可以方便地再下载一份,如果和谐了,也知道是谁的什么作品,可以去找作者联系。

用法:
    在下方设定参数,再运行此 python 脚本

'''

# ==============================================================
# 在这里设定参数

源根目录 = r'E:/'
目标根目录 = r'F:/仓库盘备份'

复制文件体积阈值 = 1000  # 单位是 kB,大于这个大小的文件不会被复制,而是会创建一个同名的空白文件
文件名匹配规则 = r'*'

# ==============================================================

def 检查路径(路径):
    if not os.path.exists(路径):
        try:
            os.makedirs(路径)
            return True
        except:
            return False
    else:
        return True

def 遍历得全部文件夹(父文件夹):
    子文件夹列表 = []
    print(f'\n正在获取所有子文件夹:{父文件夹}')
    for root, dirs, files in os.walk(父文件夹):
        子文件夹列表.append(root)
    return 子文件夹列表

def 遍历得全部文件(父文件夹):
    子文件列表 = []
    print(f'\n正在获取所有子文件:{父文件夹}')
    for root, dirs, files in os.walk(父文件夹):
        if len(files) == 0: next
        for file_ in files:
            子文件列表.append(os.path.join(root, file_))
    return 子文件列表

def 源列表转目标列表(源路径列表, 源根目录, 目标根目录):
    路径列表 = []
    for 源路径 in 源路径列表:
        目标路径 = str(pathlib.Path(目标根目录) / pathlib.Path(源路径).relative_to(源根目录))
        路径列表.append(目标路径)
    return 路径列表

def 清理废弃路径(实际路径列表, 目标路径列表):
    # 实际路径列表 表示 目前有哪些文件
    # 目标路径列表 表示 清理后要留下哪些文件
    要清理的路径集合 = set(实际路径列表) - set(目标路径列表)
    for 清理目标 in 要清理的路径集合:
        try:
            if os.path.isdir(清理目标):
                shutil.rmtree(清理目标)
            elif os.path.isfile(清理目标):
                os.remove(清理目标)
        except Exception as e:
                print(f'一个文件清理失败\n    路径:{清理目标}\n    原因:{e}')


def 得到路径Pair列表(源路径列表, 源根目录, 目标根目录):
    路径Pair列表 = []
    for 源路径 in 源路径列表:
        目标路径 = str(pathlib.Path(目标根目录) / pathlib.Path(源路径).relative_to(源根目录))
        路径Pair列表.append([源路径, 目标路径])
    return 路径Pair列表

def main():
    print('\n开始备份\n')
    global 源根目录, 目标根目录, 复制文件体积阈值, 文件名匹配规则

    if len(sys.argv) > 1:
        源根目录 = sys.argv[1]
        目标根目录 = sys.argv[2]
  
    if not 检查路径(源根目录): print(f'源目录不存在')
    if not 检查路径(目标根目录): print(f'目标目录不存在')

    # 得到源目录实际的文件夹、文件
    源目录列表 = 遍历得全部文件夹(源根目录)
    源文件列表 = 遍历得全部文件(源根目录)
  

    # 将源目录实际的文件夹、文件转为目标路径
    目标目录列表 = 源列表转目标列表(源目录列表, 源根目录, 目标根目录)
    目标文件列表 = 源列表转目标列表(源文件列表, 源根目录, 目标根目录)

    # 得到目标中实际的文件和文件夹
    目标实际目录列表 = 遍历得全部文件夹(目标根目录)
    目标实际文件列表 = 遍历得全部文件(目标根目录)

    清理废弃路径(目标实际目录列表, 目标目录列表)
    清理废弃路径(目标实际文件列表, 目标文件列表)

    目录Pair列表 = 得到路径Pair列表(源目录列表, 源根目录, 目标根目录)
    文件Pair列表 = 得到路径Pair列表(源文件列表, 源根目录, 目标根目录)

    # pprint(目录Pair列表)

    # 复制文件夹结构
    print(f'\n开始备份文件夹结构')
    for 目录Pair in tqdm.tqdm(目录Pair列表):
        检查路径(目录Pair[1])
  
    # 复制文件结构
    print(f'\n开始备份文件')
    for 文件Pair in tqdm.tqdm(文件Pair列表):
        源文件kB大小 = os.path.getsize(文件Pair[0]) / 1024
        if 源文件kB大小 <= 复制文件体积阈值 and fnmatch.fnmatch(文件Pair[0], 文件名匹配规则):
            try:
                if os.path.exists(文件Pair[1]):
                    if filecmp.cmp(文件Pair[0], 文件Pair[1]):
                        next
                shutil.copy(文件Pair[0], 文件Pair[1])
            except Exception as e:
                print(f'一个文件复制失败\n    源路径:{文件Pair[0]}\n    目标路径:{文件Pair[1]}\n    原因:{e}')
        else:
            if os.path.exists(文件Pair[1]):
                pass
            else:
                try:
                    f = open(文件Pair[1], 'wb')
                    f.close
                except Exception as e:
                    print(f'一个空白文件创建失败\n    源路径:{文件Pair[0]}\n    目标路径:{文件Pair[1]}\n    原因:{e}')
    print(f'\n完成\n')

if __name__ == '__main__':
    main()
  • Python

    Python 是一种面向对象、直译式电脑编程语言,具有近二十年的发展历史,成熟且稳定。它包含了一组完善而且容易理解的标准库,能够轻松完成很多常见的任务。它的语法简捷和清晰,尽量使用无异义的英语单词,与其它大多数程序设计语言使用大括号不一样,它使用缩进来定义语句块。

    540 引用 • 672 回帖
2 操作
HaujetZhao 在 2021-01-24 11:50:52 更新了该帖
HaujetZhao 在 2021-01-24 11:41:34 更新了该帖

相关帖子

欢迎来到这里!

我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。

注册 关于
请输入回帖内容 ...

推荐标签 标签

  • OAuth

    OAuth 协议为用户资源的授权提供了一个安全的、开放而又简易的标准。与以往的授权方式不同之处是 oAuth 的授权不会使第三方触及到用户的帐号信息(如用户名与密码),即第三方无需使用用户的用户名与密码就可以申请获得该用户资源的授权,因此 oAuth 是安全的。oAuth 是 Open Authorization 的简写。

    36 引用 • 103 回帖 • 10 关注
  • Lute

    Lute 是一款结构化的 Markdown 引擎,支持 Go 和 JavaScript。

    25 引用 • 191 回帖 • 21 关注
  • Pipe

    Pipe 是一款小而美的开源博客平台。Pipe 有着非常活跃的社区,可将文章作为帖子推送到社区,来自社区的回帖将作为博客评论进行联动(具体细节请浏览 B3log 构思 - 分布式社区网络)。

    这是一种全新的网络社区体验,让热爱记录和分享的你不再感到孤单!

    131 引用 • 1114 回帖 • 136 关注
  • 服务

    提供一个服务绝不仅仅是简单的把硬件和软件累加在一起,它包括了服务的可靠性、服务的标准化、以及对服务的监控、维护、技术支持等。

    41 引用 • 24 回帖 • 2 关注
  • DevOps

    DevOps(Development 和 Operations 的组合词)是一组过程、方法与系统的统称,用于促进开发(应用程序/软件工程)、技术运营和质量保障(QA)部门之间的沟通、协作与整合。

    45 引用 • 25 回帖 • 2 关注
  • 开源中国

    开源中国是目前中国最大的开源技术社区。传播开源的理念,推广开源项目,为 IT 开发者提供了一个发现、使用、并交流开源技术的平台。目前开源中国社区已收录超过两万款开源软件。

    7 引用 • 86 回帖
  • 正则表达式

    正则表达式(Regular Expression)使用单个字符串来描述、匹配一系列遵循某个句法规则的字符串。

    31 引用 • 94 回帖 • 1 关注
  • PWL

    组织简介

    用爱发电 (Programming With Love) 是一个以开源精神为核心的民间开源爱好者技术组织,“用爱发电”象征开源与贡献精神,加入组织,代表你将遵守组织的“个人开源爱好者”的各项条款。申请加入:用爱发电组织邀请帖
    用爱发电组织官网:https://programmingwithlove.stackoverflow.wiki/

    用爱发电组织的核心驱动力:

    • 遵守开源守则,体现开源&贡献精神:以分享为目的,拒绝非法牟利。
    • 自我保护:使用适当的 License 保护自己的原创作品。
    • 尊重他人:不以各种理由、各种漏洞进行未经允许的抄袭、散播、洩露;以礼相待,尊重所有对社区做出贡献的开发者;通过他人的分享习得知识,要留下足迹,表示感谢。
    • 热爱编程、热爱学习:加入组织,热爱编程是首当其要的。我们欢迎热爱讨论、分享、提问的朋友,也同样欢迎默默成就的朋友。
    • 倾听:正确并恳切对待、处理问题与建议,及时修复开源项目的 Bug ,及时与反馈者沟通。不抬杠、不无视、不辱骂。
    • 平视:不诋毁、轻视、嘲讽其他开发者,主动提出建议、施以帮助,以和谐为本。只要他人肯努力,你也可能会被昔日小看的人所超越,所以请保持谦虚。
    • 乐观且活跃:你的努力决定了你的高度。不要放弃,多年后回头俯瞰,才会发现自己已经成就往日所仰望的水平。积极地将项目开源,帮助他人学习、改进,自己也会获得相应的提升、成就与成就感。
    1 引用 • 487 回帖
  • TGIF

    Thank God It's Friday! 感谢老天,总算到星期五啦!

    287 引用 • 4484 回帖 • 660 关注
  • OkHttp

    OkHttp 是一款 HTTP & HTTP/2 客户端库,专为 Android 和 Java 应用打造。

    16 引用 • 6 回帖 • 53 关注
  • Scala

    Scala 是一门多范式的编程语言,集成面向对象编程和函数式编程的各种特性。

    13 引用 • 11 回帖 • 115 关注
  • golang

    Go 语言是 Google 推出的一种全新的编程语言,可以在不损失应用程序性能的情况下降低代码的复杂性。谷歌首席软件工程师罗布派克(Rob Pike)说:我们之所以开发 Go,是因为过去 10 多年间软件开发的难度令人沮丧。Go 是谷歌 2009 发布的第二款编程语言。

    497 引用 • 1386 回帖 • 324 关注
  • Gitea

    Gitea 是一个开源社区驱动的轻量级代码托管解决方案,后端采用 Go 编写,采用 MIT 许可证。

    4 引用 • 16 回帖 • 3 关注
  • Kubernetes

    Kubernetes 是 Google 开源的一个容器编排引擎,它支持自动化部署、大规模可伸缩、应用容器化管理。

    109 引用 • 54 回帖
  • SQLServer

    SQL Server 是由 [微软] 开发和推广的关系数据库管理系统(DBMS),它最初是由 微软、Sybase 和 Ashton-Tate 三家公司共同开发的,并于 1988 年推出了第一个 OS/2 版本。

    19 引用 • 31 回帖
  • 微软

    微软是一家美国跨国科技公司,也是世界 PC 软件开发的先导,由比尔·盖茨与保罗·艾伦创办于 1975 年,公司总部设立在华盛顿州的雷德蒙德(Redmond,邻近西雅图)。以研发、制造、授权和提供广泛的电脑软件服务业务为主。

    8 引用 • 44 回帖 • 1 关注
  • 链书

    链书(Chainbook)是 B3log 开源社区提供的区块链纸质书交易平台,通过 B3T 实现共享激励与价值链。可将你的闲置书籍上架到链书,我们共同构建这个全新的交易平台,让闲置书籍继续发挥它的价值。

    链书社

    链书目前已经下线,也许以后还有计划重制上线。

    14 引用 • 257 回帖
  • GitBook

    GitBook 使您的团队可以轻松编写和维护高质量的文档。 分享知识,提高团队的工作效率,让用户满意。

    3 引用 • 8 回帖
  • 资讯

    资讯是用户因为及时地获得它并利用它而能够在相对短的时间内给自己带来价值的信息,资讯有时效性和地域性。

    54 引用 • 85 回帖
  • Electron

    Electron 基于 Chromium 和 Node.js,让你可以使用 HTML、CSS 和 JavaScript 构建应用。它是一个由 GitHub 及众多贡献者组成的活跃社区共同维护的开源项目,兼容 Mac、Windows 和 Linux,它构建的应用可在这三个操作系统上面运行。

    15 引用 • 136 回帖 • 10 关注
  • Shell

    Shell 脚本与 Windows/Dos 下的批处理相似,也就是用各类命令预先放入到一个文件中,方便一次性执行的一个程序文件,主要是方便管理员进行设置或者管理用的。但是它比 Windows 下的批处理更强大,比用其他编程程序编辑的程序效率更高,因为它使用了 Linux/Unix 下的命令。

    122 引用 • 73 回帖
  • SpaceVim

    SpaceVim 是一个社区驱动的模块化 vim/neovim 配置集合,以模块的方式组织管理插件以
    及相关配置,为不同的语言开发量身定制了相关的开发模块,该模块提供代码自动补全,
    语法检查、格式化、调试、REPL 等特性。用户仅需载入相关语言的模块即可得到一个开箱
    即用的 Vim-IDE。

    3 引用 • 31 回帖 • 83 关注
  • CSDN

    CSDN (Chinese Software Developer Network) 创立于 1999 年,是中国的 IT 社区和服务平台,为中国的软件开发者和 IT 从业者提供知识传播、职业发展、软件开发等全生命周期服务,满足他们在职业发展中学习及共享知识和信息、建立职业发展社交圈、通过软件开发实现技术商业化等刚性需求。

    14 引用 • 155 回帖
  • 程序员

    程序员是从事程序开发、程序维护的专业人员。

    546 引用 • 3531 回帖 • 1 关注
  • DNSPod

    DNSPod 建立于 2006 年 3 月份,是一款免费智能 DNS 产品。 DNSPod 可以为同时有电信、网通、教育网服务器的网站提供智能的解析,让电信用户访问电信的服务器,网通的用户访问网通的服务器,教育网的用户访问教育网的服务器,达到互联互通的效果。

    6 引用 • 26 回帖 • 519 关注
  • 服务器

    服务器,也称伺服器,是提供计算服务的设备。由于服务器需要响应服务请求,并进行处理,因此一般来说服务器应具备承担服务并且保障服务的能力。

    124 引用 • 580 回帖
  • 房星科技

    房星网,我们不和没有钱的程序员谈理想,我们要让程序员又有理想又有钱。我们有雄厚的房地产行业线下资源,遍布昆明全城的 100 家门店、四千地产经纪人是我们坚实的后盾。

    6 引用 • 141 回帖 • 565 关注