Python 备份文件夹结构

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

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

相关帖子

欢迎来到这里!

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

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

推荐标签 标签

  • 外包

    有空闲时间是接外包好呢还是学习好呢?

    26 引用 • 232 回帖
  • danl
    146 关注
  • Telegram

    Telegram 是一个非盈利性、基于云端的即时消息服务。它提供了支持各大操作系统平台的开源的客户端,也提供了很多强大的 APIs 给开发者创建自己的客户端和机器人。

    5 引用 • 35 回帖
  • 安装

    你若安好,便是晴天。

    132 引用 • 1184 回帖 • 1 关注
  • Q&A

    提问之前请先看《提问的智慧》,好的问题比好的答案更有价值。

    8449 引用 • 38490 回帖 • 155 关注
  • flomo

    flomo 是新一代 「卡片笔记」 ,专注在碎片化时代,促进你的记录,帮你积累更多知识资产。

    5 引用 • 107 回帖
  • 学习

    “梦想从学习开始,事业从实践起步” —— 习近平

    171 引用 • 512 回帖
  • Hexo

    Hexo 是一款快速、简洁且高效的博客框架,使用 Node.js 编写。

    21 引用 • 140 回帖 • 2 关注
  • 星云链

    星云链是一个开源公链,业内简单的将其称为区块链上的谷歌。其实它不仅仅是区块链搜索引擎,一个公链的所有功能,它基本都有,比如你可以用它来开发部署你的去中心化的 APP,你可以在上面编写智能合约,发送交易等等。3 分钟快速接入星云链 (NAS) 测试网

    3 引用 • 16 回帖 • 6 关注
  • Solidity

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

    3 引用 • 18 回帖 • 400 关注
  • GitBook

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

    3 引用 • 8 回帖
  • Notion

    Notion - The all-in-one workspace for your notes, tasks, wikis, and databases.

    7 引用 • 40 回帖
  • GitHub

    GitHub 于 2008 年上线,目前,除了 Git 代码仓库托管及基本的 Web 管理界面以外,还提供了订阅、讨论组、文本渲染、在线文件编辑器、协作图谱(报表)、代码片段分享(Gist)等功能。正因为这些功能所提供的便利,又经过长期的积累,GitHub 的用户活跃度很高,在开源世界里享有深远的声望,并形成了社交化编程文化(Social Coding)。

    210 引用 • 2036 回帖
  • JVM

    JVM(Java Virtual Machine)Java 虚拟机是一个微型操作系统,有自己的硬件构架体系,还有相应的指令系统。能够识别 Java 独特的 .class 文件(字节码),能够将这些文件中的信息读取出来,使得 Java 程序只需要生成 Java 虚拟机上的字节码后就能在不同操作系统平台上进行运行。

    180 引用 • 120 回帖 • 3 关注
  • Swagger

    Swagger 是一款非常流行的 API 开发工具,它遵循 OpenAPI Specification(这是一种通用的、和编程语言无关的 API 描述规范)。Swagger 贯穿整个 API 生命周期,如 API 的设计、编写文档、测试和部署。

    26 引用 • 35 回帖 • 5 关注
  • WiFiDog

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

    1 引用 • 7 回帖 • 592 关注
  • 反馈

    Communication channel for makers and users.

    123 引用 • 913 回帖 • 250 关注
  • SQLServer

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

    21 引用 • 31 回帖 • 4 关注
  • 正则表达式

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

    31 引用 • 94 回帖 • 2 关注
  • 开源

    Open Source, Open Mind, Open Sight, Open Future!

    407 引用 • 3578 回帖
  • Latke

    Latke 是一款以 JSON 为主的 Java Web 框架。

    71 引用 • 535 回帖 • 789 关注
  • 创造

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

    178 引用 • 997 回帖
  • OpenShift

    红帽提供的 PaaS 云,支持多种编程语言,为开发人员提供了更为灵活的框架、存储选择。

    14 引用 • 20 回帖 • 632 关注
  • CSDN

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

    14 引用 • 155 回帖
  • MyBatis

    MyBatis 本是 Apache 软件基金会 的一个开源项目 iBatis,2010 年这个项目由 Apache 软件基金会迁移到了 google code,并且改名为 MyBatis ,2013 年 11 月再次迁移到了 GitHub。

    170 引用 • 414 回帖 • 387 关注
  • GAE

    Google App Engine(GAE)是 Google 管理的数据中心中用于 WEB 应用程序的开发和托管的平台。2008 年 4 月 发布第一个测试版本。目前支持 Python、Java 和 Go 开发部署。全球已有数十万的开发者在其上开发了众多的应用。

    14 引用 • 42 回帖 • 779 关注
  • 导航

    各种网址链接、内容导航。

    42 引用 • 175 回帖