Python 备份文件夹结构

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

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

相关帖子

欢迎来到这里!

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

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

推荐标签 标签

  • Unity

    Unity 是由 Unity Technologies 开发的一个让开发者可以轻松创建诸如 2D、3D 多平台的综合型游戏开发工具,是一个全面整合的专业游戏引擎。

    25 引用 • 7 回帖 • 174 关注
  • 面试

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

    325 引用 • 1395 回帖
  • HTML

    HTML5 是 HTML 下一个的主要修订版本,现在仍处于发展阶段。广义论及 HTML5 时,实际指的是包括 HTML、CSS 和 JavaScript 在内的一套技术组合。

    107 引用 • 295 回帖 • 1 关注
  • Android

    Android 是一种以 Linux 为基础的开放源码操作系统,主要使用于便携设备。2005 年由 Google 收购注资,并拉拢多家制造商组成开放手机联盟开发改良,逐渐扩展到到平板电脑及其他领域上。

    334 引用 • 323 回帖 • 1 关注
  • 宕机

    宕机,多指一些网站、游戏、网络应用等服务器一种区别于正常运行的状态,也叫“Down 机”、“当机”或“死机”。宕机状态不仅仅是指服务器“挂掉了”、“死机了”状态,也包括服务器假死、停用、关闭等一些原因而导致出现的不能够正常运行的状态。

    13 引用 • 82 回帖 • 52 关注
  • 996
    13 引用 • 200 回帖 • 6 关注
  • Openfire

    Openfire 是开源的、基于可拓展通讯和表示协议 (XMPP)、采用 Java 编程语言开发的实时协作服务器。Openfire 的效率很高,单台服务器可支持上万并发用户。

    6 引用 • 7 回帖 • 95 关注
  • Log4j

    Log4j 是 Apache 开源的一款使用广泛的 Java 日志组件。

    20 引用 • 18 回帖 • 31 关注
  • React

    React 是 Facebook 开源的一个用于构建 UI 的 JavaScript 库。

    192 引用 • 291 回帖 • 384 关注
  • V2Ray
    1 引用 • 15 回帖
  • etcd

    etcd 是一个分布式、高可用的 key-value 数据存储,专门用于在分布式系统中保存关键数据。

    5 引用 • 26 回帖 • 529 关注
  • PWA

    PWA(Progressive Web App)是 Google 在 2015 年提出、2016 年 6 月开始推广的项目。它结合了一系列现代 Web 技术,在网页应用中实现和原生应用相近的用户体验。

    14 引用 • 69 回帖 • 154 关注
  • H2

    H2 是一个开源的嵌入式数据库引擎,采用 Java 语言编写,不受平台的限制,同时 H2 提供了一个十分方便的 web 控制台用于操作和管理数据库内容。H2 还提供兼容模式,可以兼容一些主流的数据库,因此采用 H2 作为开发期的数据库非常方便。

    11 引用 • 54 回帖 • 654 关注
  • DNSPod

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

    6 引用 • 26 回帖 • 510 关注
  • 微软

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

    8 引用 • 44 回帖
  • Firefox

    Mozilla Firefox 中文俗称“火狐”(正式缩写为 Fx 或 fx,非正式缩写为 FF),是一个开源的网页浏览器,使用 Gecko 排版引擎,支持多种操作系统,如 Windows、OSX 及 Linux 等。

    8 引用 • 30 回帖 • 407 关注
  • HBase

    HBase 是一个分布式的、面向列的开源数据库,该技术来源于 Fay Chang 所撰写的 Google 论文 “Bigtable:一个结构化数据的分布式存储系统”。就像 Bigtable 利用了 Google 文件系统所提供的分布式数据存储一样,HBase 在 Hadoop 之上提供了类似于 Bigtable 的能力。

    17 引用 • 6 回帖 • 73 关注
  • Sphinx

    Sphinx 是一个基于 SQL 的全文检索引擎,可以结合 MySQL、PostgreSQL 做全文搜索,它可以提供比数据库本身更专业的搜索功能,使得应用程序更容易实现专业化的全文检索。

    1 引用 • 211 关注
  • Gitea

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

    4 引用 • 16 回帖 • 4 关注
  • DevOps

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

    47 引用 • 25 回帖
  • Solidity

    Solidity 是一种智能合约高级语言,运行在 [以太坊] 虚拟机(EVM)之上。它的语法接近于 JavaScript,是一种面向对象的语言。

    3 引用 • 18 回帖 • 399 关注
  • NetBeans

    NetBeans 是一个始于 1997 年的 Xelfi 计划,本身是捷克布拉格查理大学的数学及物理学院的学生计划。此计划延伸而成立了一家公司进而发展这个商用版本的 NetBeans IDE,直到 1999 年 Sun 买下此公司。Sun 于次年(2000 年)六月将 NetBeans IDE 开源,直到现在 NetBeans 的社群依然持续增长。

    78 引用 • 102 回帖 • 680 关注
  • 架构

    我们平时所说的“架构”主要是指软件架构,这是有关软件整体结构与组件的抽象描述,用于指导软件系统各个方面的设计。另外还有“业务架构”、“网络架构”、“硬件架构”等细分领域。

    142 引用 • 442 回帖
  • Vue.js

    Vue.js(读音 /vju ː/,类似于 view)是一个构建数据驱动的 Web 界面库。Vue.js 的目标是通过尽可能简单的 API 实现响应的数据绑定和组合的视图组件。

    266 引用 • 665 回帖 • 1 关注
  • Wide

    Wide 是一款基于 Web 的 Go 语言 IDE。通过浏览器就可以进行 Go 开发,并有代码自动完成、查看表达式、编译反馈、Lint、实时结果输出等功能。

    欢迎访问我们运维的实例: https://wide.b3log.org

    30 引用 • 218 回帖 • 629 关注
  • 安全

    安全永远都不是一个小问题。

    199 引用 • 816 回帖
  • 程序员

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

    567 引用 • 3532 回帖