蓝屏后文件无法读取?自动备份工作目录

蓝屏后文件读取失败

曾有惨痛的经历:工作的过程中电脑蓝屏了,重启之后之前编辑的主文件损坏、无法打开,一整个下午的东西全部无法找回了。
当时用的软件不是像Word/Powerpoint那样、缓存目录一般可以找到临时文件;我遇到的情况是,不完整的内容保存和覆盖了原始文件、导致文件结构已经损坏,而磁盘再无其他版本的备份,因此只能重新编写。

为了避免这样的事情,工作的时候实时保存工作目录是非常必要的。因此这里使用python写了一个自动备份的脚本。

不同于软件中的”自动保存“,该程序按照给定的时间间隔、把指定工作目录的文件复制到新的备份目录中去,并且维护保持多个不同时间的拷贝,也支持永久备份选项。

自动备份工作目录

整个程序在名为Backup.py的文件中。

首先引入需要的模块。click用于设定command line中的选项设定;timedatetime设定备份时候的时间戳以及计时;shutil中的copyfile负责复制文件,如果需要保持文件的metadata、可以用shutil.copy2替换copyfile

import click 
import os 
import time 
import datetime 
from shutil import copy, copyfile 

LOG = print 

定义好复制整个目录的函数。这里简便期间使用递归啥的,也没仔细地debug, 但是能用就行:

def copy_a_folder(src, dest): 
    """
    copy files from src to dest. 
    
    Invokers shall make sure the src folder exists. 
    """
    names = os.listdir(src) 
    if not os.path.exists(dest): 
        os.mkdir(dest) 
    for name in names: 
        src_new = src + "\\" + name 
        dest_new = dest + "\\" + name 
        if os.path.isdir(src_new): 
            if not os.path.exists(dest_new): 
                os.mkdir(dest_new) 
            copy_a_folder(src_new, dest_new) # REG 
        else: 
            copyfile(src_new, dest_new) 

除此之外,为了防止人为失误、待备份地目录文件夹太大了,我们至少给出一个磁盘空间的计算:

def size_of_folder(src, maxdepth=None) -> float: 
    """
    return the size of a target folder in bytes. 
    
    src: the folder 
    maxdepth: int | None, maximal depth inside the folder. 
    """
    total = 0.0 
    maxdepth = -1 if maxdepth is None else maxdepth 
    
    if maxdepth >= 0:
        
        if os.path.isfile(src): 
            total += os.path.getsize(src) 
        else:
            with os.scandir(src) as it: 
                depth = maxdepth - 1 
                for entry in it: 
                    if entry.is_file(): 
                        total += entry.stat().st_size 
                    else:
                        total += size_of_folder(entry.path, depth) 
            # 
        #
    #
    return total 

同样用了递归,代码逻辑不是最好的,但是能用。

接下来就是起主要作用的函数了。
我们使用了@click.XXX来提供命令行选项。
我们实现的功能流程大概是这样的:

  1. 首先,用户通过命令行的参数指定备份的源路径、备份路径,即时备份的时间间隔和队列总数目,永久备份时间间隔等
  2. 然后,程序计算出需要备份的源目录所需磁盘空间,让用户选择是否继续
  3. 然后备份开始:程序每分钟活动一次,判断该时刻是否需要备份。
  4. 最后,用户Ctrl+C时结束。
    代码如下:
@click.command() 
@click.option("--src", type=str, help="source folder: your working folder. Default './'.") 
@click.option("--dest", type=str, help="the backup main folder. Default 'E://Backup'.") 
@click.option("--i", type=int, help='the time interval for instant backup in minutes. Default 5.') 
@click.option("--n", type=int, help='the size of instant backup queue. Bigger than this value, folders will be covered. Default 10.') 
@click.option("--t", type=float, help='time in hour for hard backup. Default 6.') 
def startbackup(src, dest, i, n, t) -> None: 
    """
    the main function for backup 
    """ 
    if src is None: 
        src = "./" 
    if dest is None:
        dest = "E://Backup" 
    if i is None: 
        i = 5 
    if n is None: 
        n = 10 
    if t is None:
        t = 6.0  
    
    LOG("Configs: \t\n", 
        "src: ", src, 
        "\t\ni:", i, "  n:", n, "  t:", t, "\t\n")
    
    if not os.path.exists(src): 
        LOG("Error src folder: not a folder or not exists.") 
        exit(-1) 
    
    size_in_bytes = size_of_folder(src, 10) 
    LOG("src info: %.2fMB size in depth %d\t\n"%(size_in_bytes/1024.**2, 10))
    LOG("Press `c` to continue, or `q` to quit: ") 
    c = input() 
    if c.lower().startswith('q'): 
        exit(0) 
    elif c.lower().startswith('c'): 
        pass 
    else: 
        exit(0) # other than `c`, also exit. 
    
    LOG("# -------------------------------------- #\t\n") 
    
    LOG(
        "[BACKUP STARTS] ", 
        "src: %s"%src, 
        "dest: %s"%dest, 
        "Mini-Interval: %d minutes."%i, 
        "Hard-Interval: %.2f hours."%t, 
        "Mini-Cache Size: %d."%n, 
        "", 
        "Press Ctrl+C to stop.",  
        "="*30, 
        sep="\t\n" 
    )
    
    tstart = time.time() 
    minute = 60.0 
    hour = 60.0 * 60.0 # [sec] 
    
    dests = [os.path.join(dest, "B%d"%k) for k in range(1, n+1)] 
    k = 0 
    miniintervalstart = tstart 
    hardbackstart = tstart 
    FIRST = True 
    while True:
        end = time.time() 
        
        if end - miniintervalstart >= i * minute or FIRST: 
            # mini backup 
            now = datetime.datetime.now() 
            tmp = now.strftime("%Y-%m-%d%H:%M:%S:") 
            desti = dests[k] 
            LOG(tmp, "MINI BACKUP TO ", desti) 
            
            copy_a_folder(src, desti) 
            
            k = (k + 1) % n # next backup folder. 
            miniintervalstart = end 
        
        if end - hardbackstart >= t * hour or FIRST: 
            # hard backup 
            now = datetime.datetime.now() 
            foldername = 'BACK_' + now.strftime("%Y-%m-%d-%H%M%S") 
            desti = os.path.join(dest, foldername) 
            tmp = now.strftime("%Y-%m-%d%H:%M:%S:") 
            
            LOG(tmp, "HARD BACKUP TO ", desti) 
            copy_a_folder(src, desti) 
            
            hardbackstart = end 
        FIRST = False 
        time.sleep(60) 

最后,需要使用__main__的环境调用:

if __name__ == "__main__": 
    startbackup() 

应用时需要安装python3环境。
比如我在D盘有个目录需要备份,结构如下:
D:\I_am_a_working_folder
│ F0.txt

├─tempFolder1
│ │ F0.txt
│ │
│ └─subFolder1
│ f11.txt

└─tempFolder2
F2.txt
F3.txt
然后,上述python代码放到了这个路径:C:\Backup\Backup.py
想要放置备份的主目录是E:\Backup,并且已在E盘建立了该目录。命令行输入python后看到python能用(即python路径加入了环境变量,否则可以使用python.exe的全路径代替)。
接下来,自动备份启动。注意这是一行指令,确认好空格、半角引号。然后回车:

PS C:\Windows\system32> python -u C:\Backup\Backup.py --src "D:\I_am_a_working_folder" --dest "E:\Backup" --i 5 --n 10 --t 4
Configs:
 src:  D:\I_am_a_working_folder
i: 5   n: 10   t: 4.0

src info: 0.05MB size in depth 10

Press `c` to continue, or `q` to quit:

此时Configs后面给出了当前的备份设定:
src: 源目录。
i: 5 每隔5分钟复制一份即时备份?
n: 10 即时备份的总的备份数目为10。当超出的时候、最旧的目录将会被覆盖掉。
t: 4.0 每隔4.0个小时,保存一份永久备份。这些文件将会被永久储存在dest的目录内的子目录中、并以时间戳标识(如果未来不需要,则应择机手动删除)。
然后src info后面表示了源目录的文件总大小,(这里的目录层次最多是10,一般够了,如果需要改程序即可QAQ)。 如果这个size太大,一定要仔细考虑是否真的要这么备份!

输入c回车,即可开启自动备份。然后你可以随意编辑工作目录D:\I_am_a_working_folder内部的内容了。但不要关闭这个命令终端!

c
# -------------------------------------- #

[BACKUP STARTS]
src: D:\I_am_a_working_folder
dest: E:\Backup
Mini-Interval: 5 minutes.
Hard-Interval: 4.00 hours.
Mini-Cache Size: 10.

Press Ctrl+C to stop.
==============================
2024-02-2502:06:25: MINI BACKUP TO  E:\Backup\B1
2024-02-2502:06:25: HARD BACKUP TO  E:\Backup\BACK_2024-02-25-020625
2024-02-2502:11:25: MINI BACKUP TO  E:\Backup\B2
...

备份过程中,会不断记录备份行为。
要想结束这个备份过程有几种可选方式:

  1. 在这个终端窗口,英文输入状态下按Ctrl+C即可中断执行、停止备份,然后关闭窗口即可。
  2. 直接关闭终端窗口
    打开dest的目录(E:\Backup),可以找到备份:
    B1, B2, B3, … 是临时备份文件,由–i 和–n指定备份测略。
    BACK_2024-02-25-020625等为永久备份,由–t指定间隔小时数目(支持小数)。

这样,妈妈再也不用担心工作文件突然死机丢掉啦~

====
环境: Windows, python3.8

  • 18
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值