web技术

用Python检测是否有新增和修改的文件

2023-10-16 13:56 作者:Admin原创

坐我隔壁的美女前端工程师,这几天总是疑神疑鬼,总是怀疑有人黑进她的电脑修改了她的文件,甚至可能在她的前端程序中植入了恶意代码。为此她过来找我帮忙,希望能帮她写一个文件检测程序,运行程序就能快速找出被修改过和新增的文件。

呃,这个需求我刚好也需要,想做很久了,但还是假装出勉为其难的样子,我跟她说做这个很麻烦,我又很忙,每天晚上都要加班到八九点,实在没空做这个,除非……除非你给我什么好处,嘿嘿嘿……最后,美女同意给我买一杯4元的蜜雪冰城柠檬水作为犒劳,哈哈,又成功骗了一杯柠檬水。

一、思路

1、价值4元的程序,我不想写得太复杂,暂不采用后台实时监控,需要美女前端自己手动运行 Python 程序检测。但不排除以后会升级为实时监控。

2、需要先生成一份“指纹档案”,记录要检测的目录中的每一个文件的路径、文件MD5、文件大小、创建日期、修改日期等,后面检测的时候,以这份“指纹档案”为基准进行对比。这份档案不会自动更新,一段时间后需要手动运行程序重新生成。

3、“指纹档案”需要用文件或数据库存储,考虑到前端工程师的电脑中一般没有安装 mysql 之类的数据库,所以我决定用 Excel 存储数据。

4、根据前面三点,这个程序需要4个文件:

① 文件 20131016.xlsx 是“指纹档案”文件,以日期作为版本号命名;
②文件 01.py 用于遍历目录并生成指纹档案;
③文件 02.py 用于遍历目录并与指纹档案对比,将发现的差异(新增和修改)输出;
④文件 functions.py 是自定义公共函数库,用于存放 01.py 和 02.py 的公共函数。

二、自定义公共函数库

新建 functions.py 文件,代码如下:

import os
import hashlib
from openpyxl import load_workbook

# 向 Excel 工作表追加一行数据
def append_row(file_path,sheet_name,data):
    workbook = load_workbook(file_path)
    sheet = workbook[sheet_name]
    sheet.append(data)
    workbook.save(file_path)

# 获取文件 MD5 值
def md5_hash_file(filename):
    with open(filename, 'rb') as f:
        md5 = hashlib.md5(f.read()).hexdigest()
    return md5

# 递归遍历目录,返回一个文件路径列表
def traverse_dir(path):
    r = []
    for root, dirs, files in os.walk(path):
        for file in files:
            r.append(os.path.join(root,file))
    return r

# 获取文件创建时间、修改时间、文件大小
def get_file_info(file_path):
    info = {}
    # 创建时间
    info['add_time'] = os.path.getctime(file_path)

    # 修改时间
    info['edit_time'] = os.path.getmtime(file_path)

    # 文件大小 (字节)
    info['file_size'] = os.path.getsize(file_path)

    return info

append_row() 函数用于向 Excel 文件追加一行数据,参数 data 是要追加的行数据列表。

md5_hash_file() 函数用于计算文件的 MD5 值。

traverse_dir() 函数递归遍历目录,返回一个文件路径列表。

get_file_info() 函数用于获取文件创建时间、修改时间、文件大小,时间以时间戳表示。

三、创建“指纹档案”

首先需要创建一个空白的 Excel 文档,扩展名为 xlsx 。在 windows 系统中,一般在桌面空白处点右键,新建“Microsoft Excel 工作表”即可。将其命名为 20131016.xlsx,这是以日期作为版本号,你也可以自主采用其它命名方案。

然后新建 01.py 文件:

from functions import append_row, md5_hash_file, traverse_dir, get_file_info

# 要检测的文件夹(目录)
target = 'E:\workspace\python'

# 设置文件名和工作表名,大小写敏感
file_path = '20131016.xlsx'
sheet_name = 'Sheet1'

# 表头
data = ['文件路径','文件MD5','文件旧MD5','文件大小','创建日期','修改日期']
append_row(file_path,sheet_name,data)

files = traverse_dir(target)
for file in files:
    print(file)
    info = get_file_info(file)
    data = [file,md5_hash_file(file),'-',info['file_size'],info['add_time'],info['edit_time']]
    append_row(file_path,sheet_name,data)

这段代码首先调用 append_row() 函数向 Excel 文件中添加了一个表头,然后使用 traverse_dir() 函数递归遍历目标目录,获得一个文件列表 files。循环处理 files 列表,使用 get_file_info() 函数获取每个文件的属性信息,将这些信息拼接成一行数据 data,调用 append_row() 将行数据追加写入 Excel 文档。

运行这段代码,可以看到 Excel 文档里已经有了内容,可能多达上千行。对于同一个 Excel 文件,不能重复运行 01.py,如果要重新生成指纹档案,须先重新创建一个空白的 Excel 文档。

指纹档案不会自动更新,用户须根据需要每过一段时间重新运行 01.py 程序生成新的指纹档案。

四、检测文件

在“指纹档案”创建一段时间之后,需要运行一段检测程序来查找新增和修改的文件。

02.py 文件:

import time
from openpyxl import load_workbook
from functions import md5_hash_file, traverse_dir, get_file_info

# 要检测的文件夹(目录)
target = 'E:\workspace\python'

# 设置文件名和工作表名,大小写敏感
file_path = '20131016.xlsx'
sheet_name = 'Sheet1'

# 加载 Excel 文件
workbook = load_workbook(file_path)
# 选择工作表
sheet = workbook[sheet_name]

new_files = []
edited = []

t = 1
files = traverse_dir(target)
for file in files:
    is_new = True
    print('检查文件' + str(t) + ': ' + file)
    t = t + 1
    info = get_file_info(file)
    file_md5 = md5_hash_file(file)
    rows = sheet.iter_rows(min_row=2, max_row=sheet.max_row, min_col=1, max_col=sheet.max_column, values_only=True)
    for row in rows:
        if row[0] == file:
            is_new = False
            if round(info['edit_time']) > round(row[5]):
            # if file_md5 != row[1]:
                edit_time = time.strftime("%Y-%m-%d %H:%M:%S",time.localtime(info['edit_time']))
                edited.append([file,edit_time])
    if is_new == True:
        add_time = time.strftime("%Y-%m-%d %H:%M:%S",time.localtime(info['add_time']))
        new_files.append([file,add_time])

print('新增的文件:')
for file in new_files:
    print(file)

print('修改过的文件:')
for file in edited:
    print(file)

在这段程序中,首先使用 openpyxl 库的 load_workbook() 函数加载 Excel 文件,并选择工作表。调用 traverse_dir() 函数获取目标检测目录的文件列表 files,然后循环处理 files,在循环中使用 sheet.iter_rows() 获取 Excel 工作表中从第2行起的所有数据,得到的是一个二维列表 rows,继续循环处理 rows。如果 row[0] == file,说明 file 不是新文件;如果 info['edit_time'] 大于 row[5],说明文件 file 的修改时间晚于指纹档案中记录的时间,即说明该文件被修改过,要注意 info['edit_time'] 和 row[5] 要用 round()函数取整,否则可能出现小数误差。

将新文件的路径和创建时间组成列表,追加到 new_files 列表;将有改动的文件的路径和修改时间组成列表,追加到 edited 列表。最后打印这两个列表。

这段程序中虽然调用 md5_hash_file() 函数获得一个 MD5 值,但没有使用该值,这里只作为备用,在一些比较严格的场景中,需要通过 MD5 来判断文件是否被修改,可以将

if round(info['edit_time']) > round(row[5]):

改为:

if file_md5 != row[1]:

至此,检测文件是否有新增和修改的 Python 程序就完成了。

推荐文章
如何批量修改文件名?你可能在网上搜到了许多方法,但操作起来并不简单,有...
同事找我帮忙,让我帮他写一个Python程序,用来删除Excel中的重复行。于是我...
如何使用Python在Excel中删除行?实际情景中往往是要求按条件删除、批量删除...
如何使用 Python 在 Excel 查找数据?如何实现模糊查找和精确查找?如何在一...
本文讲解如何使用Python在Excel工作表中添加列(追加一列)和插入列(在指定...
推荐专题
如何自己建网站?建网站难不难?其实建网站说难不难,说容易也并不容易,难...
本专题精心收集整理了多种HTML+CSS+JS轮播图实现方案,带详细代码和讲解,正...