Python 备份文件夹结构

本贴最后更新于 1188 天前,其中的信息可能已经事过景迁
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 是一种面向对象、直译式电脑编程语言,具有近二十年的发展历史,成熟且稳定。它包含了一组完善而且容易理解的标准库,能够轻松完成很多常见的任务。它的语法简捷和清晰,尽量使用无异义的英语单词,与其它大多数程序设计语言使用大括号不一样,它使用缩进来定义语句块。

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

相关帖子

欢迎来到这里!

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

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

推荐标签 标签

  • Vditor

    Vditor 是一款浏览器端的 Markdown 编辑器,支持所见即所得、即时渲染(类似 Typora)和分屏预览模式。它使用 TypeScript 实现,支持原生 JavaScript、Vue、React 和 Angular。

    313 引用 • 1667 回帖 • 1 关注
  • OpenStack

    OpenStack 是一个云操作系统,通过数据中心可控制大型的计算、存储、网络等资源池。所有的管理通过前端界面管理员就可以完成,同样也可以通过 Web 接口让最终用户部署资源。

    10 引用 • 6 关注
  • 面试

    面试造航母,上班拧螺丝。多面试,少加班。

    324 引用 • 1395 回帖
  • Ngui

    Ngui 是一个 GUI 的排版显示引擎和跨平台的 GUI 应用程序开发框架,基于
    Node.js / OpenGL。目标是在此基础上开发 GUI 应用程序可拥有开发 WEB 应用般简单与速度同时兼顾 Native 应用程序的性能与体验。

    7 引用 • 9 回帖 • 345 关注
  • 微服务

    微服务架构是一种架构模式,它提倡将单一应用划分成一组小的服务。服务之间互相协调,互相配合,为用户提供最终价值。每个服务运行在独立的进程中。服务于服务之间才用轻量级的通信机制互相沟通。每个服务都围绕着具体业务构建,能够被独立的部署。

    96 引用 • 155 回帖
  • RabbitMQ

    RabbitMQ 是一个开源的 AMQP 实现,服务器端用 Erlang 语言编写,支持多种语言客户端,如:Python、Ruby、.NET、Java、C、PHP、ActionScript 等。用于在分布式系统中存储转发消息,在易用性、扩展性、高可用性等方面表现不俗。

    49 引用 • 60 回帖 • 399 关注
  • FFmpeg

    FFmpeg 是一套可以用来记录、转换数字音频、视频,并能将其转化为流的开源计算机程序。

    22 引用 • 31 回帖 • 3 关注
  • WiFiDog

    WiFiDog 是一套开源的无线热点认证管理工具,主要功能包括:位置相关的内容递送;用户认证和授权;集中式网络监控。

    1 引用 • 7 回帖 • 545 关注
  • 京东

    京东是中国最大的自营式电商企业,2015 年第一季度在中国自营式 B2C 电商市场的占有率为 56.3%。2014 年 5 月,京东在美国纳斯达克证券交易所正式挂牌上市(股票代码:JD),是中国第一个成功赴美上市的大型综合型电商平台,与腾讯、百度等中国互联网巨头共同跻身全球前十大互联网公司排行榜。

    14 引用 • 102 回帖 • 405 关注
  • Electron

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

    15 引用 • 136 回帖 • 7 关注
  • 创造

    你创造的作品可能会帮助到很多人,如果是开源项目的话就更赞了!

    173 引用 • 990 回帖
  • Maven

    Maven 是基于项目对象模型(POM)、通过一小段描述信息来管理项目的构建、报告和文档的软件项目管理工具。

    185 引用 • 318 回帖 • 344 关注
  • 电影

    这是一个不能说的秘密。

    120 引用 • 597 回帖
  • LeetCode

    LeetCode(力扣)是一个全球极客挚爱的高质量技术成长平台,想要学习和提升专业能力从这里开始,充足技术干货等你来啃,轻松拿下 Dream Offer!

    209 引用 • 72 回帖 • 2 关注
  • SQLServer

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

    19 引用 • 31 回帖 • 2 关注
  • 单点登录

    单点登录(Single Sign On)是目前比较流行的企业业务整合的解决方案之一。SSO 的定义是在多个应用系统中,用户只需要登录一次就可以访问所有相互信任的应用系统。

    9 引用 • 25 回帖 • 2 关注
  • Ubuntu

    Ubuntu(友帮拓、优般图、乌班图)是一个以桌面应用为主的 Linux 操作系统,其名称来自非洲南部祖鲁语或豪萨语的“ubuntu”一词,意思是“人性”、“我的存在是因为大家的存在”,是非洲传统的一种价值观,类似华人社会的“仁爱”思想。Ubuntu 的目标在于为一般用户提供一个最新的、同时又相当稳定的主要由自由软件构建而成的操作系统。

    123 引用 • 168 回帖
  • OkHttp

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

    16 引用 • 6 回帖 • 54 关注
  • HHKB

    HHKB 是富士通的 Happy Hacking 系列电容键盘。电容键盘即无接点静电电容式键盘(Capacitive Keyboard)。

    5 引用 • 74 回帖 • 407 关注
  • Spark

    Spark 是 UC Berkeley AMP lab 所开源的类 Hadoop MapReduce 的通用并行框架。Spark 拥有 Hadoop MapReduce 所具有的优点;但不同于 MapReduce 的是 Job 中间输出结果可以保存在内存中,从而不再需要读写 HDFS,因此 Spark 能更好地适用于数据挖掘与机器学习等需要迭代的 MapReduce 的算法。

    74 引用 • 46 回帖 • 549 关注
  • 工具

    子曰:“工欲善其事,必先利其器。”

    275 引用 • 682 回帖
  • SQLite

    SQLite 是一个进程内的库,实现了自给自足的、无服务器的、零配置的、事务性的 SQL 数据库引擎。SQLite 是全世界使用最为广泛的数据库引擎。

    4 引用 • 7 回帖 • 3 关注
  • 周末

    星期六到星期天晚,实行五天工作制后,指每周的最后两天。再过几年可能就是三天了。

    14 引用 • 297 回帖
  • Hibernate

    Hibernate 是一个开放源代码的对象关系映射框架,它对 JDBC 进行了非常轻量级的对象封装,使得 Java 程序员可以随心所欲的使用对象编程思维来操纵数据库。

    39 引用 • 103 回帖 • 685 关注
  • golang

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

    492 引用 • 1383 回帖 • 375 关注
  • Docker

    Docker 是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的操作系统上。容器完全使用沙箱机制,几乎没有性能开销,可以很容易地在机器和数据中心中运行。

    476 引用 • 899 回帖
  • Kafka

    Kafka 是一种高吞吐量的分布式发布订阅消息系统,它可以处理消费者规模的网站中的所有动作流数据。 这种动作(网页浏览,搜索和其他用户的行动)是现代系统中许多功能的基础。 这些数据通常是由于吞吐量的要求而通过处理日志和日志聚合来解决。

    35 引用 • 35 回帖