最新消息: USBMI致力于为网友们分享Windows、安卓、IOS等主流手机系统相关的资讯以及评测、同时提供相关教程、应用、软件下载等服务。

有效整理电脑上的文件:清理电脑文件方案需要 -- 合理的方法 + 合适的工具如Python查找重复文件

业界 admin 15浏览 0评论

有效管理电脑文档

  • 出发点
    • 推荐一适合大众用户的省时好用懒人方法
  • 管好文件的基础
    • 一. 数据/文件的分类
    • 二. 数据/文件存放的地方
    • 三. 数据/文件名称和文件夹名称的规范和技巧
  • 查询重复文件的工具和方法
    • 现成查询工具
    • 网上的 Python 分享
    • 另一种解决方案的思路
      • 第一步:用下面的Dos命令遍历文件夹
      • 第二步:对上面的DOS输出表进行清洗
      • 第三步:构建->文件夹 + 文件名
      • 第四步:读出MD5值生成一个总表
      • 第五步:对比总表找出重复值
      • 第六步?可能最有效的清理手段->压缩包
  • 体会

出发点

用电脑已数十年,在这个过程中经历了软件系统的崩溃,硬盘的损坏,主板挂了,电脑的更新,外存的更迭,日积月累攒了很多数据/文件,有几十G到几百G,有时为了重要的照片,特意备份了好几次,为花了数月的项目保存了各个阶段的备份,而整理这些数据是一件很头痛的事情,当然也可以不管,反正现在存储介质越来越便宜,在此推荐一个最懒的方法,只要你把握好,基本就可以很快找到你需要的东西。

推荐一适合大众用户的省时好用懒人方法

前提条件:

  1. 所有数据都在本地win电脑上;
  2. 文件名都有自己的特征,容易辨别,一看文件名就知道里面的内容;
  3. 电脑上安装了查询神器Listary,详细信息请看前面链接里介绍。

这是一个最省时间又好用的懒人方法,对于个人+数据量不大同时又很少换电脑的用户应该是一个最佳方案,只要你能够把第二点做好,同时安装Listary,一般来说就可以避免找不到文件的窘境,即使在一团乱麻里也立马可以找到有特征的文件,这个方法应该可以满足95%个人用户;世上没有对所有人一样的最好方法,只有最适合你的方法;如果选择这个 懒人方案 就不必看下面的介绍了

对于整天用电脑工作的人来说就需要花更多的心思来考虑一下这个问题,这样才能更快找到你所需要的数据或文件,避免重复劳动,避免有价值资料被埋没和被遗忘。在过去的很长时间里一直在找合适的工具,一直想把重复的文件找出来,同时再把文件规整一下,但一直没有找到合适tool,直到最近看到一些Python的分享才见到了希望,同时也看到仅仅靠工具还是不够的,基础应该是更重要,所以我们还是从基础开始。

管好文件的基础

虽然有上面的懒人方法,但这还是会有后遗症,最晚在迁移时你就会发现问题,所以打好基础非常重要,没有好的基础盖不出好楼,无规矩不成方圆。
在没有文件系统的帮助下对于这件事通常来说要从下面 三个角度 来考虑:

一. 数据/文件的分类

a. 对于个人来说重要+隐密性数据(跟财产或身份认证有关的密码、密匙、证件或密照,最高密级),这类数据保密性要求高但数量和体积相对都很小,这些数据可以多处备份;
b. 个人和家庭信息(相对来说保密要求不高,如来往信件、各种申请/求职、每月账单、保单、各种证明等);
c. 照片、视频和音频(这类体积非常大,当然也有很多没有保留价值的或垃圾);
d. 教育/学习类(书籍、教育视频、学习资料等);
e. 跟工作相关的,现实中在企业里使用员工私人电脑非常普遍,所以把私人数据跟公司数据分离也是要注意的地方;
f. 软件,这方面使用习惯会造成很大差异,为避免不必要的病毒风险,使用自己验证过的无病毒软件包是个更稳妥的方法,而且更省时间。

这里说的是常用分类(可根据自己需求做个性化配置),可以区别对待这些分类,这也是有条理的管理的基础,所以很重要!

二. 数据/文件存放的地方

当你走进一间办公室,扫一眼电脑屏幕,绝大部分的电脑桌面上都是满满当当,电脑桌面干干净净的主,一般都是摆摆样子的,他的电脑不是干活用的;每个人都有自己的习惯和爱好,桌面是一个很方便和直观的地方,但不是长期保存文件的好地方,因为桌面在C盘,不易过大,对于单台电脑来说数据/文件存到哪里也是有一定讲究;
通常推荐电脑共分4个盘,分别为C,D,E,F,盘;下图是推荐给企业的规范,个人也可以参考。
一般C盘可以设置100G,如果有经验可以相应减小,D盘100G也够了,剩下的可以根据需求分给E和F,F是你的电脑公私两用才需要。这样分盘的一个重要好处除了有条理外还有,在Win系统出问题的情况下,E盘数据可以很方便的复制出来,重装win也可以不覆盖E盘数据。
除此之外我们通常还有移动硬盘、U盘、云盘、SAN或局域网的共享硬盘等;在此稍微花点时间理解和规划会让你在以后得到丰厚的回报,合理对重要文件进行多重备份,如移动硬盘+云盘备份,会让你减轻或避免突发事件的影响。

这个地方会被很多人忽视,大部分人也许始终过得很好,一辈子没有麻烦,但肯定也有不少人已经有过惨痛的教训。这是为了最大程度上避免数据丢失,同时方便迁移

企业数据安全布局请看本文最后一行XNOM网友的分享。

三. 数据/文件名称和文件夹名称的规范和技巧

好的名称:一目了然,让人不用进一步查看就知道里面的内容,避免让人产生疑问,此外还有其他的属性如:所属人、地点-时间、创建时间、序列号:版本号、序号。
最好是唯一的,同时有特点好记+易搜索
如果需要分隔文件名的关键词,用下划线,而不是空格。
在文件名末尾引入文件版本管理和文件编号。
名称里除了西文的句号“.”不要夹带逗号、分号、减号、引号和问号等。
不同场景不同需求,灵活运用规则进行命名。比如从同事处接收的文档,就保持源文件名,这样能够方便协同工作。

编号文件名例子
1支付宝_阿宝_月报_2021.11.xlsx (阿宝为帐号所有者,月份2021.11)
2苏州河夜景_阿狗_2021.10_SDIM8079.X3F
(阿狗为拍摄者,SDIM8079.X3F为照片原始文件名)

如果工作单位没有要求也许没有多少人会如此自律,在私人领域几乎没有人会为此花时间,只是你现在翻看20年前的照片时,也许你会觉得有必要,当然如果你掌握了一些改名称工具以后会发现其实没有那么费事。有特点名称对用工具快速查询非常关键

关于批量修改文件名的分享

要做到以上三个方面相对来说还不算难,如果从一开始就做也不需要花很多时间,同时可以记录很多非常重要的信息。
要继续下面的步骤就需要一定的耐心和技巧了,如果没有耐心做到上面三部就可以收手了。

这里还有一篇关于文件夹名称的规范,这也是应该遵守的原则

查询重复文件的工具和方法

如前所说用电脑已经数十年,积攒了大量的资料,电脑也换了好几波了,现在也同时用好几台电脑,其次还用局域网的共享硬盘,所以情况相对复杂一些,日积月累产生了不少重复的文件,首先想到的是用现成工具。

现成查询工具

关于查询工具在网上有很多分享,有些介绍也非常详细,在下面列出一些供参考:
Duplicate Cleaner
Ashisoft Duplicate File Finder Pro
EF Duplicate MP3 Finder
Puran Duplicate File Finder
FindDuplicate 这5款的介绍
DoubleKiller
dupeGuru
CCleaner Free
这些工具都有一个特点在重复数量很少的情况下有可操作性,量大了以后实际上太费时间,几乎让人看不到结束的希望。所以在用了几次CCleaner Free以后就不了了之了。

网上的 Python 分享

在网上可以搜到很多关于查找重复文件的Python分享,但对使用者还是有一定的要求,至少要会搭建Python环境,下面两个分享应该够详细:1.windows下安装Python,2.Win, iOS, Unix Python环境搭建。

下面是测试过可以跑的网上分享

#coding:utf-8

import os

def walk(dirname):
    '''
    以绝对路径,用列表输出指定目录下的所有文件,以及子文件夹下的文件。
    
    '''
    names = []
    for name in os.listdir(dirname):
        # os.listdir() Return a list containing the names of the entries in the directory given by path.

        path = os.path.join(dirname, name)
        # os.path.join() Join one or more path components intelligently

        if os.path.isfile(path):
            # os.path.isfile() Return True if path is an existing regular file.判断是否为文件
            names.append(path)
        else:
            names.extend(walk(path)) # list.extend()

    return names    # 返回指定文件下所有文件的列表

def find_suffix_file(dirname, suffix):

    '''
    以列表输出指定后缀名的文件。
    '''
    target_files = []
    
    names = walk(dirname) # 调用自定义函数walk()
    
    for name in names:
        
        if name.endswith(suffix):
            target_files.append(name)
            
    return target_files     # 返回目标文件列表

def call_cmd(cmd):

    '''
    windows下文件MD5等校验:(LINUX 下,使用md5sum命令)

    certutil -hashfile 路径/file.exe MD5

    certutil -hashfile 路径/file.exe SHA1

    certutil -hashfile 路径/file.exe SHA256
    
    '''

    fp = os.popen(cmd)  # Python下调用系统命令行,返回一个文件对象
    # Open a pipe to or from command cmd.
    # The return value is an open file object connected to the pipe,
    # which can be read or written depending on whether mode is 'r' (default) or 'w'.

    result = fp.read() # 读取命令行执行的返回的内容

    state = fp.close()   # 关闭文件对象
    
    assert state is None     # 断言文件对象是否关闭

    return result   # 返回命令行计算的结果

def compute_md5(filename):

    '''
    compute the MD5 value of the file
    '''

    # 构建命令行 命令
    
    cmd = 'certutil -hashfile "' + filename + '" MD5'

    # 注意:命令构建时,由于文件路径中含有空格,命令行执行时会将空格识别为分隔符,
    # 误识别为多个参数,从而报错 " CertUtil: 参数太多 "。
    # 所以要将文件路径包含在双引号""内。
    
    result = call_cmd(cmd)  # 调用CMD,计算MD5值
    
    file_md5 = tuple(result.split('\n'))[1] # 解析读取的内容,

    return file_md5     # 返回文件的MD5值
    
def check_file(dirname, suffix):

    d = {} # 创建空字典。将md5_value作为key, file 作为value.
    
    target_files = find_suffix_file(dirname, suffix)

    for file in target_files:

        md5_value = compute_md5(file)   # 计算md5_value

        if md5_value in d:  # 

            d[md5_value].append(file)   # 以列表的形式收集相同MD5值的file
        else:
            d[md5_value] = [file]

    for md5_value, file in d.items():

        if len(file)>1:     # 如果大于1,说明很可能有不同文件名的重复文件。

            print(file)     # 此处file是收集重复文件的列表

if __name__ == '__main__':

    # 注:指定目录下,文件路径中含有空格时会报错 AssertionError

    dirname = r'D:\CloudMusic'   #注意 Windows下路径的写法

    suffix = '.mp3'

    check_file(dirname, suffix)

原文出处:Python【习题】查找指定目录下重复文件并打印出来
但这个程序不容错,如果有一个空文件程序就会出错,还有其他出错的可能,另外这次程序太慢,50多G的数据需要10个小时以上,如果出错还要从头来,所以这个程序只能用于小数据量。

另一种解决方案的思路

全部用Python逐个读文件在数量很大的时候速度还是一个问题,在Windows, Linux 上都有原生的遍历文件夹的命令,速度要快很多,然后用这个文件再去读文件的MD5值,然后对比MD5值找出重复文件,这个要快很多,不过还是有不少麻烦,如果有中文windows,英文windows和其他西语windows混在一起还是有很多一般人意想不到的问题。下面介绍一些必须的步骤:

第一步:用下面的Dos命令遍历文件夹

这个Dos命令非常快,几秒就可以了,存为folders.txt

dir d:\software /s >folders.txt

打开 folders.txt 文件

 驱动器 D 中的卷是 doc
 卷的序列号是 16E2-F484


 D:\software 的目录

2020/10/28  20:28    <DIR>          .
2020/10/28  20:28    <DIR>          ..
2020/10/28  20:51    <DIR>          Adobe Acrobat DC 2018 SP
2019/01/03  10:58        32,044,568 BaiduNetdisk_6.7.0.8.exe
2020/08/03  05:47    <DIR>          e6440_driver
2020/05/10  11:02        76,324,794 FirefoxPortable64-76.0.zip
2020/08/03  05:47    <DIR>          FirefoxPortable64-81
2020/08/08  06:23       148,454,821 gnucash-4.0.setup.exe
2019/01/02  10:10         4,366,368 npp.7.6.2.Installer.exe
2020/08/03  05:47    <DIR>          printer
2020/08/13  06:45    <DIR>          tools
2019/09/09  12:01         7,941,304 TreeSizeFreeSetup.exe
2019/02/07  08:13        37,926,600 WeChat_C1012.exe
2020/07/04  19:36            28,258 wolcmd.zip
               7 个文件    307,086,713 字节

 D:\software\Adobe Acrobat DC 2018 SP 的目录
 ......
 D:\software\tools\wolcmd 的目录

2020/08/13  06:44    <DIR>          .
2020/08/13  06:44    <DIR>          ..
2020/08/13  06:44            50,176 WolCmd.exe
               1 个文件         50,176 字节

     所列文件总数:
            2014 个文件  2,352,871,091 字节
             815 个目录 249,901,621,248 可用字节

Linux 下用 ls -lR >folders.txt 也非常快。

接下来可以用Python完成下面的步骤

第二步:对上面的DOS输出表进行清洗

这个是比较难弄的部分,因为不确定性很大,是因人而异,比如:大小为0的文件,含逗号或问号的文件名等等都会出错,这还都是说得清楚问题,还有不知缘由的错误,所以Code就略过。如果你的文件比较简单,也许没有这么麻烦,也就不需要这一步,直接做第三步就可以了,如果有问题会不断打断第四步,直到问题都排除;在Linux上问题要少很多。

第三步:构建->文件夹 + 文件名

用Python处理,在这一步要注意的是 impfilename -> folders.txt也就是第一步导出的文件的名称和格式是否和下面的程序匹配,如果不完全匹配就需要更改几个参数。

# 构建 文件夹+文件名 如例子 D:\software\WeChat_C1012.exe
import pandas as pd
from pandas import DataFrame
import time
import chardet

impfilename = 'E:\\temp\\folders.txt'  # 文件夹名根据情况调整
expfilename = 'E:\\temp\\导出文件名.txt'

print('开始时间Begin:', time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()))
f = open(impfilename,'rb')
content = f.read()
result = chardet.detect(content)
f.close()
coding = result.get('encoding')
df = pd.read_csv(impfilename,header= None,encoding=coding,sep=';')
# 中文版
dateformat = '%Y/%m/%d'  # 中国日期格式
directory = ' 的目录'
erase = '<DIR>          .| 个文件| 可用字节|卷的序列号是|驱动器'
df = df[~df[0].str.contains(erase)]
df[1] = df[0].str[36:]  # 截取文件名
df[2] = df[0].str[33:35]  # 截取文件大小的最后两位 =' 0'要排除
df[3] = df[0].str[:10]
df[3] = pd.to_datetime(df[3], format=dateformat, errors='coerce')
df_dir = df
df_dir.loc[df_dir[0].str.contains(directory), 1] = df_dir[0].str[1:-4]
df_dir.loc[df_dir[0].str.contains(directory), 2] = directory
df_dir = df_dir.drop(df_dir[df_dir[2] == ' 0'].index)  # 删除大小为0的行

df_dir_columns = df_dir.columns
df_dir_filename = list(df_dir[df_dir_columns[1]].values)
df_dir_dimtext = list(df_dir[df_dir_columns[2]].values)
df_dir_date = list(df_dir[df_dir_columns[3]].values)
filename=[]
for i in range(len(df_dir_filename)):
    if df_dir_dimtext[i] == directory:
        fdirectory = df_dir_filename[i]
        i = i + 1
        while pd.notnull(df_dir_date[i]) == True:
            filename.append(fdirectory + "\\" + df_dir_filename[i])
            i = i + 1
        if i >= len(df_dir_filename):
            break
    else:
        # skip entry
        pass
DataFrame(filename).to_csv(expfilename, quoting=1, mode='w', index=False, header=False, encoding='utf-8')
print('结束时间End:', time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()))

输出结果:

"D:\software\BaiduNetdisk_6.7.0.8.exe"
"D:\software\FirefoxPortable64-76.0.zip"
"D:\software\gnucash-4.0.setup.exe"
"D:\software\npp.7.6.2.Installer.exe"
"D:\software\TreeSizeFreeSetup.exe"
"D:\software\WeChat_C1012.exe"
"D:\software\wolcmd.zip"
"D:\software\Adobe Acrobat DC 2018 SP\ABCPY.INI"
"D:\software\Adobe Acrobat DC 2018 SP\AcroPro.msi"
............
"D:\software\tools\ccsetup568.exe"
"D:\software\tools\HDTune Pro v5.6\HDTune Pro v5.6.exe"
"D:\software\tools\HDTune Pro v5.6\SN.txt"
"D:\software\tools\wolcmd\WolCmd.exe"

大概的速度:从几千到几万条都在几秒钟内完成。

第四步:读出MD5值生成一个总表

这步是花费时间长的步骤,因为电脑要逐个访问文件,也是容易出错的部分,因为即使在win看似没有问题的文件,用Dos命令访问时也有可能出错。
最后产生的是一张 文件夹 + 文件名 + md5码 的总表

import pandas as pd
from pandas import DataFrame
import time
import os

impfilename = 'E:\\temp\\你的导入文件名.txt'
expfilename = 'E:\\temp\\filename_md5no.txt'

df = pd.read_csv(impfilename, header=0, encoding="utf-8", sep=';')
df_columns = df.columns
df_filename = list(df[df_columns[0]].values)
df_md5 =[]

def call_cmd(cmd):
    # print(cmd)
    fp = os.popen(cmd)  # Python下调用系统命令行,返回一个文件对象
    result = fp.read()  # 读取命令行执行的返回的内容
    state = fp.close()  # 关闭文件对象
    return result  # 返回命令行计算的结果

def compute_md5(filename):
    # 构建命令行 命令
    cmd = 'certutil -hashfile "' + filename + '" MD5'
    try:
        result = call_cmd(cmd)  # 调用CMD,计算MD5值
        file_md5 = tuple(result.split('\n'))[1]  # 解析读取的内容,
    except FileNmaeError:
        print('Error: Invalid argument. i:', i,'出错文件名:' ,filename)
    return file_md5  # 返回文件的MD5值

if __name__ == '__main__':
    # exportzeil = []
    print('开始时间Begin:', time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()))
    print (df_filename)
    print (df.columns)

    for i in range(len(df_filename)):
        filename = df_filename[i]
        md5nr_s = compute_md5(filename)
        df_md5.append("'" + filename + "'" + ";" + md5nr_s)
        i = i + 1

    df2 = df_md5[0:]
    DataFrame(df2).to_csv(expfilename, quoting=0, mode='w', index=False, header=False, encoding='utf-8')
    print('结束时间End:', time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()))

输出的结果长这样:

‘D:\software\BaiduNetdisk_6.7.0.8.exe’;5e1f5a17f624ce31dfca9456b62caaff
‘D:\software\FirefoxPortable64-76.0.zip’;6a7959a947ec63b50a5dab7c0bdea0b4
… … … …
‘D:\software\tools\wolcmd\WolCmd.exe’;803d8f3dcea3ac390a5e371c83c33061

这一步可以灵活使用,如果文件夹里的数量太大可以分开处理,然后人工合并到这个表里,再通过下面第五步进行对比,这样对处理错误非常方便,可操作强,也可用于跟不同存储介质的比较,逐步反复清理,最终节省总的处理时间。

第五步:对比总表找出重复值

在第四步的总表里通过对比找出重复的文件,把第四步和第五步分开是为了更灵活、更快地进行对比,在需要的时候可以分段完成总表,如果想清楚了也许就会喜欢这种做法。

import pandas as pd
from pandas import DataFrame

impfilename = 'E:\\temp\\filename_md5no.txt'   #更换相应的文件名
expfilename = 'E:\\temp\\d_md5_files.txt'

df = pd.read_csv(impfilename, header=None,sep=';',names=['name', 'md5'])
filenames =  list(df['name'].values)
md5s = list(df['md5'].values)
d = {}
d_name=[]
for i in range(len(filenames)):
    md5 = md5s[i]
    filename = filenames[i]
    if md5 in d:
        d[md5].append(filename)
        i=i+1
    else:
        d[md5] = [filename]
        i=i+1
for md6, file in d.items():    
    if len(file)>1:
        d_name.append(file)
df2 = d_name[1:]
DataFrame(df2).to_csv(expfilename, quoting=0, mode='w', index=False, header=False, encoding='utf-8',sep=';')

重复的文件名输出

d:\software\FirefoxPortable64-81\FirefoxPortable64\App\DefaultData\settings\FirefoxPortableSettings.ini; d:\software\FirefoxPortable64-81\FirefoxPortable64\Data\settings\FirefoxPortableSettings.ini 
d:\software\FirefoxPortable64-81\FirefoxPortable64\Other\Source\License.txt; d:\software\FirefoxPortable64-81\FirefoxPortable64\Data\profile\gmp-widevinecdm\4.10.1582.2\License.txt
............

在数据量大的情况下重复的文件名有可能会很长,可以在EXCEL里处理,原则上不建议用全自动处理,因为自动删除太容易,等发现出错已经晚了,所以不建议全自动删除。

这里还可以借助编辑器如Notepad++里的列编辑功能,批量修改DOS或LINUX文件操作命令,这样就可以快速+稳妥处理文件,可以在相对短时间里把文件和文件夹清理干净。

第六步?可能最有效的清理手段->压缩包

在处理50多G文件的过程中,发现不少老数据只要稍加处理就可以大大减轻管理的负担,从数据的数量上讲,自己产生的文件数量非常有限,自产文件数量最多的可能是照片,但有保存价值的照片数量应该也很有限;数量最大的可能学习资料特别是软件包,项目数据或上网上下载的资料,这些资料时间性比较强,有些可以删除,但有些还是有保留价值,在这里介绍一种方法,可以大大减少文件数量。
例如软件包 wordpress-5.2.4 有1835个文件,如果再弄几个版本,文件数就翻几倍,所以这类文件包,只要半年以上不访问的话,这些数据就应该打包,为了方便查找除了压缩包外用dir命令再做这个压缩包的文件清单,这样就既可以减少文件数量,就可以照顾到查询速度。在这个50多G大小的具体案例里,把原本18万多的文件压缩到2万以下。

wordpress-5.2.4压缩前压缩后
文件数量18352
文件大小43MB12MB
Dos命令解释
dir e:\temp /t:w /s遍历e:\temp,显示最后修改时间
dir e:\temp /t:a /s遍历e:\temp,显示最后访问时间

项目数据也可以这样处理。

从实际的情况来说这一步应该放在最前面,先把文件特别多的文件夹(如软件包或项目数据)导出目录清单,然后压缩打包,当然是目前不需要的文件;在刚刚启动清理的1T移动硬盘里得到下面的结果:

1T移动硬盘原始状态初步整理后
目录清单行数33万18000条
文件大小282G143G
这样可以大大缩短第一到第五步的时间,特别是第四步。

体会

用MD5对比可以找出所有重复的文件,不查不知道,一查吓一跳,重复10次到20次的文件有不少,通过查找重复文件还可以很快发现一些结构性问题,可以通过调整文件夹结构来更合理规整文档。养成良好的习惯,定期清理文档也很重要,在你还可以清晰记得这些文档用途的时候就给赋予有意义和特征的名称,存到相应的文件夹了,不要等到你的记忆有点模糊了才做这些工作,两者耗时的差距是非常大的。 合适的方法和工具很重要,也许不是一蹴而就,而是需要来来回回试几次才能找到最佳的途径。
可以尝试的另一类工具->文件管理器。
如何高效率整理电脑上的文件 ?作者:XNOM 这个分享很不错

有效管理电脑文档

  • 出发点
    • 推荐一适合大众用户的省时好用懒人方法
  • 管好文件的基础
    • 一. 数据/文件的分类
    • 二. 数据/文件存放的地方
    • 三. 数据/文件名称和文件夹名称的规范和技巧
  • 查询重复文件的工具和方法
    • 现成查询工具
    • 网上的 Python 分享
    • 另一种解决方案的思路
      • 第一步:用下面的Dos命令遍历文件夹
      • 第二步:对上面的DOS输出表进行清洗
      • 第三步:构建->文件夹 + 文件名
      • 第四步:读出MD5值生成一个总表
      • 第五步:对比总表找出重复值
      • 第六步?可能最有效的清理手段->压缩包
  • 体会

出发点

用电脑已数十年,在这个过程中经历了软件系统的崩溃,硬盘的损坏,主板挂了,电脑的更新,外存的更迭,日积月累攒了很多数据/文件,有几十G到几百G,有时为了重要的照片,特意备份了好几次,为花了数月的项目保存了各个阶段的备份,而整理这些数据是一件很头痛的事情,当然也可以不管,反正现在存储介质越来越便宜,在此推荐一个最懒的方法,只要你把握好,基本就可以很快找到你需要的东西。

推荐一适合大众用户的省时好用懒人方法

前提条件:

  1. 所有数据都在本地win电脑上;
  2. 文件名都有自己的特征,容易辨别,一看文件名就知道里面的内容;
  3. 电脑上安装了查询神器Listary,详细信息请看前面链接里介绍。

这是一个最省时间又好用的懒人方法,对于个人+数据量不大同时又很少换电脑的用户应该是一个最佳方案,只要你能够把第二点做好,同时安装Listary,一般来说就可以避免找不到文件的窘境,即使在一团乱麻里也立马可以找到有特征的文件,这个方法应该可以满足95%个人用户;世上没有对所有人一样的最好方法,只有最适合你的方法;如果选择这个 懒人方案 就不必看下面的介绍了

对于整天用电脑工作的人来说就需要花更多的心思来考虑一下这个问题,这样才能更快找到你所需要的数据或文件,避免重复劳动,避免有价值资料被埋没和被遗忘。在过去的很长时间里一直在找合适的工具,一直想把重复的文件找出来,同时再把文件规整一下,但一直没有找到合适tool,直到最近看到一些Python的分享才见到了希望,同时也看到仅仅靠工具还是不够的,基础应该是更重要,所以我们还是从基础开始。

管好文件的基础

虽然有上面的懒人方法,但这还是会有后遗症,最晚在迁移时你就会发现问题,所以打好基础非常重要,没有好的基础盖不出好楼,无规矩不成方圆。
在没有文件系统的帮助下对于这件事通常来说要从下面 三个角度 来考虑:

一. 数据/文件的分类

a. 对于个人来说重要+隐密性数据(跟财产或身份认证有关的密码、密匙、证件或密照,最高密级),这类数据保密性要求高但数量和体积相对都很小,这些数据可以多处备份;
b. 个人和家庭信息(相对来说保密要求不高,如来往信件、各种申请/求职、每月账单、保单、各种证明等);
c. 照片、视频和音频(这类体积非常大,当然也有很多没有保留价值的或垃圾);
d. 教育/学习类(书籍、教育视频、学习资料等);
e. 跟工作相关的,现实中在企业里使用员工私人电脑非常普遍,所以把私人数据跟公司数据分离也是要注意的地方;
f. 软件,这方面使用习惯会造成很大差异,为避免不必要的病毒风险,使用自己验证过的无病毒软件包是个更稳妥的方法,而且更省时间。

这里说的是常用分类(可根据自己需求做个性化配置),可以区别对待这些分类,这也是有条理的管理的基础,所以很重要!

二. 数据/文件存放的地方

当你走进一间办公室,扫一眼电脑屏幕,绝大部分的电脑桌面上都是满满当当,电脑桌面干干净净的主,一般都是摆摆样子的,他的电脑不是干活用的;每个人都有自己的习惯和爱好,桌面是一个很方便和直观的地方,但不是长期保存文件的好地方,因为桌面在C盘,不易过大,对于单台电脑来说数据/文件存到哪里也是有一定讲究;
通常推荐电脑共分4个盘,分别为C,D,E,F,盘;下图是推荐给企业的规范,个人也可以参考。
一般C盘可以设置100G,如果有经验可以相应减小,D盘100G也够了,剩下的可以根据需求分给E和F,F是你的电脑公私两用才需要。这样分盘的一个重要好处除了有条理外还有,在Win系统出问题的情况下,E盘数据可以很方便的复制出来,重装win也可以不覆盖E盘数据。
除此之外我们通常还有移动硬盘、U盘、云盘、SAN或局域网的共享硬盘等;在此稍微花点时间理解和规划会让你在以后得到丰厚的回报,合理对重要文件进行多重备份,如移动硬盘+云盘备份,会让你减轻或避免突发事件的影响。

这个地方会被很多人忽视,大部分人也许始终过得很好,一辈子没有麻烦,但肯定也有不少人已经有过惨痛的教训。这是为了最大程度上避免数据丢失,同时方便迁移

企业数据安全布局请看本文最后一行XNOM网友的分享。

三. 数据/文件名称和文件夹名称的规范和技巧

好的名称:一目了然,让人不用进一步查看就知道里面的内容,避免让人产生疑问,此外还有其他的属性如:所属人、地点-时间、创建时间、序列号:版本号、序号。
最好是唯一的,同时有特点好记+易搜索
如果需要分隔文件名的关键词,用下划线,而不是空格。
在文件名末尾引入文件版本管理和文件编号。
名称里除了西文的句号“.”不要夹带逗号、分号、减号、引号和问号等。
不同场景不同需求,灵活运用规则进行命名。比如从同事处接收的文档,就保持源文件名,这样能够方便协同工作。

编号文件名例子
1支付宝_阿宝_月报_2021.11.xlsx (阿宝为帐号所有者,月份2021.11)
2苏州河夜景_阿狗_2021.10_SDIM8079.X3F
(阿狗为拍摄者,SDIM8079.X3F为照片原始文件名)

如果工作单位没有要求也许没有多少人会如此自律,在私人领域几乎没有人会为此花时间,只是你现在翻看20年前的照片时,也许你会觉得有必要,当然如果你掌握了一些改名称工具以后会发现其实没有那么费事。有特点名称对用工具快速查询非常关键

关于批量修改文件名的分享

要做到以上三个方面相对来说还不算难,如果从一开始就做也不需要花很多时间,同时可以记录很多非常重要的信息。
要继续下面的步骤就需要一定的耐心和技巧了,如果没有耐心做到上面三部就可以收手了。

这里还有一篇关于文件夹名称的规范,这也是应该遵守的原则

查询重复文件的工具和方法

如前所说用电脑已经数十年,积攒了大量的资料,电脑也换了好几波了,现在也同时用好几台电脑,其次还用局域网的共享硬盘,所以情况相对复杂一些,日积月累产生了不少重复的文件,首先想到的是用现成工具。

现成查询工具

关于查询工具在网上有很多分享,有些介绍也非常详细,在下面列出一些供参考:
Duplicate Cleaner
Ashisoft Duplicate File Finder Pro
EF Duplicate MP3 Finder
Puran Duplicate File Finder
FindDuplicate 这5款的介绍
DoubleKiller
dupeGuru
CCleaner Free
这些工具都有一个特点在重复数量很少的情况下有可操作性,量大了以后实际上太费时间,几乎让人看不到结束的希望。所以在用了几次CCleaner Free以后就不了了之了。

网上的 Python 分享

在网上可以搜到很多关于查找重复文件的Python分享,但对使用者还是有一定的要求,至少要会搭建Python环境,下面两个分享应该够详细:1.windows下安装Python,2.Win, iOS, Unix Python环境搭建。

下面是测试过可以跑的网上分享

#coding:utf-8

import os

def walk(dirname):
    '''
    以绝对路径,用列表输出指定目录下的所有文件,以及子文件夹下的文件。
    
    '''
    names = []
    for name in os.listdir(dirname):
        # os.listdir() Return a list containing the names of the entries in the directory given by path.

        path = os.path.join(dirname, name)
        # os.path.join() Join one or more path components intelligently

        if os.path.isfile(path):
            # os.path.isfile() Return True if path is an existing regular file.判断是否为文件
            names.append(path)
        else:
            names.extend(walk(path)) # list.extend()

    return names    # 返回指定文件下所有文件的列表

def find_suffix_file(dirname, suffix):

    '''
    以列表输出指定后缀名的文件。
    '''
    target_files = []
    
    names = walk(dirname) # 调用自定义函数walk()
    
    for name in names:
        
        if name.endswith(suffix):
            target_files.append(name)
            
    return target_files     # 返回目标文件列表

def call_cmd(cmd):

    '''
    windows下文件MD5等校验:(LINUX 下,使用md5sum命令)

    certutil -hashfile 路径/file.exe MD5

    certutil -hashfile 路径/file.exe SHA1

    certutil -hashfile 路径/file.exe SHA256
    
    '''

    fp = os.popen(cmd)  # Python下调用系统命令行,返回一个文件对象
    # Open a pipe to or from command cmd.
    # The return value is an open file object connected to the pipe,
    # which can be read or written depending on whether mode is 'r' (default) or 'w'.

    result = fp.read() # 读取命令行执行的返回的内容

    state = fp.close()   # 关闭文件对象
    
    assert state is None     # 断言文件对象是否关闭

    return result   # 返回命令行计算的结果

def compute_md5(filename):

    '''
    compute the MD5 value of the file
    '''

    # 构建命令行 命令
    
    cmd = 'certutil -hashfile "' + filename + '" MD5'

    # 注意:命令构建时,由于文件路径中含有空格,命令行执行时会将空格识别为分隔符,
    # 误识别为多个参数,从而报错 " CertUtil: 参数太多 "。
    # 所以要将文件路径包含在双引号""内。
    
    result = call_cmd(cmd)  # 调用CMD,计算MD5值
    
    file_md5 = tuple(result.split('\n'))[1] # 解析读取的内容,

    return file_md5     # 返回文件的MD5值
    
def check_file(dirname, suffix):

    d = {} # 创建空字典。将md5_value作为key, file 作为value.
    
    target_files = find_suffix_file(dirname, suffix)

    for file in target_files:

        md5_value = compute_md5(file)   # 计算md5_value

        if md5_value in d:  # 

            d[md5_value].append(file)   # 以列表的形式收集相同MD5值的file
        else:
            d[md5_value] = [file]

    for md5_value, file in d.items():

        if len(file)>1:     # 如果大于1,说明很可能有不同文件名的重复文件。

            print(file)     # 此处file是收集重复文件的列表

if __name__ == '__main__':

    # 注:指定目录下,文件路径中含有空格时会报错 AssertionError

    dirname = r'D:\CloudMusic'   #注意 Windows下路径的写法

    suffix = '.mp3'

    check_file(dirname, suffix)

原文出处:Python【习题】查找指定目录下重复文件并打印出来
但这个程序不容错,如果有一个空文件程序就会出错,还有其他出错的可能,另外这次程序太慢,50多G的数据需要10个小时以上,如果出错还要从头来,所以这个程序只能用于小数据量。

另一种解决方案的思路

全部用Python逐个读文件在数量很大的时候速度还是一个问题,在Windows, Linux 上都有原生的遍历文件夹的命令,速度要快很多,然后用这个文件再去读文件的MD5值,然后对比MD5值找出重复文件,这个要快很多,不过还是有不少麻烦,如果有中文windows,英文windows和其他西语windows混在一起还是有很多一般人意想不到的问题。下面介绍一些必须的步骤:

第一步:用下面的Dos命令遍历文件夹

这个Dos命令非常快,几秒就可以了,存为folders.txt

dir d:\software /s >folders.txt

打开 folders.txt 文件

 驱动器 D 中的卷是 doc
 卷的序列号是 16E2-F484


 D:\software 的目录

2020/10/28  20:28    <DIR>          .
2020/10/28  20:28    <DIR>          ..
2020/10/28  20:51    <DIR>          Adobe Acrobat DC 2018 SP
2019/01/03  10:58        32,044,568 BaiduNetdisk_6.7.0.8.exe
2020/08/03  05:47    <DIR>          e6440_driver
2020/05/10  11:02        76,324,794 FirefoxPortable64-76.0.zip
2020/08/03  05:47    <DIR>          FirefoxPortable64-81
2020/08/08  06:23       148,454,821 gnucash-4.0.setup.exe
2019/01/02  10:10         4,366,368 npp.7.6.2.Installer.exe
2020/08/03  05:47    <DIR>          printer
2020/08/13  06:45    <DIR>          tools
2019/09/09  12:01         7,941,304 TreeSizeFreeSetup.exe
2019/02/07  08:13        37,926,600 WeChat_C1012.exe
2020/07/04  19:36            28,258 wolcmd.zip
               7 个文件    307,086,713 字节

 D:\software\Adobe Acrobat DC 2018 SP 的目录
 ......
 D:\software\tools\wolcmd 的目录

2020/08/13  06:44    <DIR>          .
2020/08/13  06:44    <DIR>          ..
2020/08/13  06:44            50,176 WolCmd.exe
               1 个文件         50,176 字节

     所列文件总数:
            2014 个文件  2,352,871,091 字节
             815 个目录 249,901,621,248 可用字节

Linux 下用 ls -lR >folders.txt 也非常快。

接下来可以用Python完成下面的步骤

第二步:对上面的DOS输出表进行清洗

这个是比较难弄的部分,因为不确定性很大,是因人而异,比如:大小为0的文件,含逗号或问号的文件名等等都会出错,这还都是说得清楚问题,还有不知缘由的错误,所以Code就略过。如果你的文件比较简单,也许没有这么麻烦,也就不需要这一步,直接做第三步就可以了,如果有问题会不断打断第四步,直到问题都排除;在Linux上问题要少很多。

第三步:构建->文件夹 + 文件名

用Python处理,在这一步要注意的是 impfilename -> folders.txt也就是第一步导出的文件的名称和格式是否和下面的程序匹配,如果不完全匹配就需要更改几个参数。

# 构建 文件夹+文件名 如例子 D:\software\WeChat_C1012.exe
import pandas as pd
from pandas import DataFrame
import time
import chardet

impfilename = 'E:\\temp\\folders.txt'  # 文件夹名根据情况调整
expfilename = 'E:\\temp\\导出文件名.txt'

print('开始时间Begin:', time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()))
f = open(impfilename,'rb')
content = f.read()
result = chardet.detect(content)
f.close()
coding = result.get('encoding')
df = pd.read_csv(impfilename,header= None,encoding=coding,sep=';')
# 中文版
dateformat = '%Y/%m/%d'  # 中国日期格式
directory = ' 的目录'
erase = '<DIR>          .| 个文件| 可用字节|卷的序列号是|驱动器'
df = df[~df[0].str.contains(erase)]
df[1] = df[0].str[36:]  # 截取文件名
df[2] = df[0].str[33:35]  # 截取文件大小的最后两位 =' 0'要排除
df[3] = df[0].str[:10]
df[3] = pd.to_datetime(df[3], format=dateformat, errors='coerce')
df_dir = df
df_dir.loc[df_dir[0].str.contains(directory), 1] = df_dir[0].str[1:-4]
df_dir.loc[df_dir[0].str.contains(directory), 2] = directory
df_dir = df_dir.drop(df_dir[df_dir[2] == ' 0'].index)  # 删除大小为0的行

df_dir_columns = df_dir.columns
df_dir_filename = list(df_dir[df_dir_columns[1]].values)
df_dir_dimtext = list(df_dir[df_dir_columns[2]].values)
df_dir_date = list(df_dir[df_dir_columns[3]].values)
filename=[]
for i in range(len(df_dir_filename)):
    if df_dir_dimtext[i] == directory:
        fdirectory = df_dir_filename[i]
        i = i + 1
        while pd.notnull(df_dir_date[i]) == True:
            filename.append(fdirectory + "\\" + df_dir_filename[i])
            i = i + 1
        if i >= len(df_dir_filename):
            break
    else:
        # skip entry
        pass
DataFrame(filename).to_csv(expfilename, quoting=1, mode='w', index=False, header=False, encoding='utf-8')
print('结束时间End:', time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()))

输出结果:

"D:\software\BaiduNetdisk_6.7.0.8.exe"
"D:\software\FirefoxPortable64-76.0.zip"
"D:\software\gnucash-4.0.setup.exe"
"D:\software\npp.7.6.2.Installer.exe"
"D:\software\TreeSizeFreeSetup.exe"
"D:\software\WeChat_C1012.exe"
"D:\software\wolcmd.zip"
"D:\software\Adobe Acrobat DC 2018 SP\ABCPY.INI"
"D:\software\Adobe Acrobat DC 2018 SP\AcroPro.msi"
............
"D:\software\tools\ccsetup568.exe"
"D:\software\tools\HDTune Pro v5.6\HDTune Pro v5.6.exe"
"D:\software\tools\HDTune Pro v5.6\SN.txt"
"D:\software\tools\wolcmd\WolCmd.exe"

大概的速度:从几千到几万条都在几秒钟内完成。

第四步:读出MD5值生成一个总表

这步是花费时间长的步骤,因为电脑要逐个访问文件,也是容易出错的部分,因为即使在win看似没有问题的文件,用Dos命令访问时也有可能出错。
最后产生的是一张 文件夹 + 文件名 + md5码 的总表

import pandas as pd
from pandas import DataFrame
import time
import os

impfilename = 'E:\\temp\\你的导入文件名.txt'
expfilename = 'E:\\temp\\filename_md5no.txt'

df = pd.read_csv(impfilename, header=0, encoding="utf-8", sep=';')
df_columns = df.columns
df_filename = list(df[df_columns[0]].values)
df_md5 =[]

def call_cmd(cmd):
    # print(cmd)
    fp = os.popen(cmd)  # Python下调用系统命令行,返回一个文件对象
    result = fp.read()  # 读取命令行执行的返回的内容
    state = fp.close()  # 关闭文件对象
    return result  # 返回命令行计算的结果

def compute_md5(filename):
    # 构建命令行 命令
    cmd = 'certutil -hashfile "' + filename + '" MD5'
    try:
        result = call_cmd(cmd)  # 调用CMD,计算MD5值
        file_md5 = tuple(result.split('\n'))[1]  # 解析读取的内容,
    except FileNmaeError:
        print('Error: Invalid argument. i:', i,'出错文件名:' ,filename)
    return file_md5  # 返回文件的MD5值

if __name__ == '__main__':
    # exportzeil = []
    print('开始时间Begin:', time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()))
    print (df_filename)
    print (df.columns)

    for i in range(len(df_filename)):
        filename = df_filename[i]
        md5nr_s = compute_md5(filename)
        df_md5.append("'" + filename + "'" + ";" + md5nr_s)
        i = i + 1

    df2 = df_md5[0:]
    DataFrame(df2).to_csv(expfilename, quoting=0, mode='w', index=False, header=False, encoding='utf-8')
    print('结束时间End:', time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()))

输出的结果长这样:

‘D:\software\BaiduNetdisk_6.7.0.8.exe’;5e1f5a17f624ce31dfca9456b62caaff
‘D:\software\FirefoxPortable64-76.0.zip’;6a7959a947ec63b50a5dab7c0bdea0b4
… … … …
‘D:\software\tools\wolcmd\WolCmd.exe’;803d8f3dcea3ac390a5e371c83c33061

这一步可以灵活使用,如果文件夹里的数量太大可以分开处理,然后人工合并到这个表里,再通过下面第五步进行对比,这样对处理错误非常方便,可操作强,也可用于跟不同存储介质的比较,逐步反复清理,最终节省总的处理时间。

第五步:对比总表找出重复值

在第四步的总表里通过对比找出重复的文件,把第四步和第五步分开是为了更灵活、更快地进行对比,在需要的时候可以分段完成总表,如果想清楚了也许就会喜欢这种做法。

import pandas as pd
from pandas import DataFrame

impfilename = 'E:\\temp\\filename_md5no.txt'   #更换相应的文件名
expfilename = 'E:\\temp\\d_md5_files.txt'

df = pd.read_csv(impfilename, header=None,sep=';',names=['name', 'md5'])
filenames =  list(df['name'].values)
md5s = list(df['md5'].values)
d = {}
d_name=[]
for i in range(len(filenames)):
    md5 = md5s[i]
    filename = filenames[i]
    if md5 in d:
        d[md5].append(filename)
        i=i+1
    else:
        d[md5] = [filename]
        i=i+1
for md6, file in d.items():    
    if len(file)>1:
        d_name.append(file)
df2 = d_name[1:]
DataFrame(df2).to_csv(expfilename, quoting=0, mode='w', index=False, header=False, encoding='utf-8',sep=';')

重复的文件名输出

d:\software\FirefoxPortable64-81\FirefoxPortable64\App\DefaultData\settings\FirefoxPortableSettings.ini; d:\software\FirefoxPortable64-81\FirefoxPortable64\Data\settings\FirefoxPortableSettings.ini 
d:\software\FirefoxPortable64-81\FirefoxPortable64\Other\Source\License.txt; d:\software\FirefoxPortable64-81\FirefoxPortable64\Data\profile\gmp-widevinecdm\4.10.1582.2\License.txt
............

在数据量大的情况下重复的文件名有可能会很长,可以在EXCEL里处理,原则上不建议用全自动处理,因为自动删除太容易,等发现出错已经晚了,所以不建议全自动删除。

这里还可以借助编辑器如Notepad++里的列编辑功能,批量修改DOS或LINUX文件操作命令,这样就可以快速+稳妥处理文件,可以在相对短时间里把文件和文件夹清理干净。

第六步?可能最有效的清理手段->压缩包

在处理50多G文件的过程中,发现不少老数据只要稍加处理就可以大大减轻管理的负担,从数据的数量上讲,自己产生的文件数量非常有限,自产文件数量最多的可能是照片,但有保存价值的照片数量应该也很有限;数量最大的可能学习资料特别是软件包,项目数据或上网上下载的资料,这些资料时间性比较强,有些可以删除,但有些还是有保留价值,在这里介绍一种方法,可以大大减少文件数量。
例如软件包 wordpress-5.2.4 有1835个文件,如果再弄几个版本,文件数就翻几倍,所以这类文件包,只要半年以上不访问的话,这些数据就应该打包,为了方便查找除了压缩包外用dir命令再做这个压缩包的文件清单,这样就既可以减少文件数量,就可以照顾到查询速度。在这个50多G大小的具体案例里,把原本18万多的文件压缩到2万以下。

wordpress-5.2.4压缩前压缩后
文件数量18352
文件大小43MB12MB
Dos命令解释
dir e:\temp /t:w /s遍历e:\temp,显示最后修改时间
dir e:\temp /t:a /s遍历e:\temp,显示最后访问时间

项目数据也可以这样处理。

从实际的情况来说这一步应该放在最前面,先把文件特别多的文件夹(如软件包或项目数据)导出目录清单,然后压缩打包,当然是目前不需要的文件;在刚刚启动清理的1T移动硬盘里得到下面的结果:

1T移动硬盘原始状态初步整理后
目录清单行数33万18000条
文件大小282G143G
这样可以大大缩短第一到第五步的时间,特别是第四步。

体会

用MD5对比可以找出所有重复的文件,不查不知道,一查吓一跳,重复10次到20次的文件有不少,通过查找重复文件还可以很快发现一些结构性问题,可以通过调整文件夹结构来更合理规整文档。养成良好的习惯,定期清理文档也很重要,在你还可以清晰记得这些文档用途的时候就给赋予有意义和特征的名称,存到相应的文件夹了,不要等到你的记忆有点模糊了才做这些工作,两者耗时的差距是非常大的。 合适的方法和工具很重要,也许不是一蹴而就,而是需要来来回回试几次才能找到最佳的途径。
可以尝试的另一类工具->文件管理器。
如何高效率整理电脑上的文件 ?作者:XNOM 这个分享很不错

发布评论

评论列表 (0)

  1. 暂无评论