20年前构思过想要实现的这个东西,当时刻录盘太多了,需要找到某个东西很难。如今我把东西都往仓库硬盘里塞,逐渐硬盘数量也多起来。想找部旧电影来重温太麻烦,反复插拔了几个盘都没找到。

不能忍,用1小时把代码写了顺便把全部硬盘里的主要文件做了索引。

QQ截图20200306131952.png

当年没有这个技术,现在用python+php+mysql实现起来相当简单的样子。
也不知道是技术变得平易近人还是我变厉害了..

20年前用 DOS命令 dir /s , tree /f > diskinfo.txt 然后再对一堆 txt 做文本检索。

现在用得主要命令是python 的 os.walk() 遍历整个盘。

代码简单概括如下(PHP部分略了,仅仅是查库)


#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# 扫描硬盘分区构建文件索引存库
# Copyright 2020 <snmoney@gmail.com>
# win version
# 只有文件夹 与 大于 5M 的文件会被记录,太小的文件则直接忽略,
# 避免很多广告文件或者无关的小文件会增加数据库负担
# 像解压的漫画之类的可以忽略文件,只检索到目录就够了

import os
import mysql.connector
from mysql.connector import Error
from mysql.connector import errorcode

#借用网上别人的代码片段,字节转可读得文件大小
def sizeReadable(size, is_disk=False, precision=2):

    formats = ['KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB']
    unit = 1000.0 if is_disk else 1024.0
    if not(isinstance(size, float) or isinstance(size, int)):
        raise TypeError('a float number or an integer number is required!')
    if size < 0:
        raise ValueError('number must be non-negative')
    for i in formats:
        size /= unit
        if size < unit:
            return str(round(size, precision)) + i
    return str(round(size, precision)) + i



minFileSize = 5000000 #5M文件大小下限

inpDrv = input("扫描的盘符(不带,如 c 代表 C:\ ):")
inpDrv = inpDrv.upper()
inpDiskName = input("给磁盘一个名称:")

scanPath = inpDrv+":\\"


db_cfg = mysql.connector.connect(
            host="localhost",
            user="db_username",
            passwd="db_password",
            database="db_dbname"
        )
db = db_cfg.cursor()

print((inpDiskName))

#写入一个磁盘名
sql = "INSERT INTO `disk_name`(`dname`) VALUES ('"+inpDiskName+"');"

try:
    #db.execute(sql, vals)
    db.execute(sql)
    db_cfg.commit()

    #获取 diskId
    diskId = str(db.lastrowid)

except mysql.connector.Error as err:
    print("mysql_err @diskname insert:", inpDiskName, err.msg)
    diskId = 0

sql = "INSERT INTO `disk_tree`(`diskid`, `path`, `filename`, `filesize`) VALUES (%s, %s, %s, %s);"

fileTree = os.walk(scanPath)

matchCount = 0;
for i in fileTree:

    #如果是空目录则记录目录名称
    if(len(i[2])==0):
        filename = "__DIR__" #特殊名称标记为目录
        vals = (diskId, i[0], filename, '0')
        db.execute(sql, vals)

    else :
        bigfilecount = 0 #如果目录下没有5M的文件,还是需要记录一个空目录
        for f in i[2]:
            try:
                realPath = os.path.join(i[0], f)
                fileSize = os.path.getsize(realPath)
                if fileSize >= minFileSize : #小于5M不入库
                    #print(realPath, sizeReadable(fileSize)) #debug
                    matchCount += 1
                    bigfilecount += 1
                    vals = (diskId, i[0], f, sizeReadable(fileSize))
                    db.execute(sql, vals)
            except OSError as err :
                #部分文件可能村怀或特殊的文件名导致文件系统无法正确操作
                #skip
                print(str(err))

        if bigfilecount == 0 :
            filename = "__DIR__"
            vals = (diskId, i[0], filename, '0')
            db.execute(sql, vals)

    db_cfg.commit() #每个文件夹提交一次

print("all match files:", matchCount)

标签: none

添加新评论