该小程序的功能主要是通过用户的输入条件来将电脑中所有盘符下相应的文件筛选出来,主要是通过正则表达式来将所需的文件路径筛选出来,主要的选项有:
-f : 筛选包含该字串的文件(只列举文件) -d :筛选包含该字串的目录(将该目录下的文件都列举出来)-a :筛选包含该字串的文件或目录(将该文件和目录都列举出来)
-h :筛选包含该文件后缀的文件,在这些选项前,还有一个选项,就是要判断用户输入的是否包含有文件后缀,当用户输入有文件后缀时,筛选的条件就变得有些不一样了。
首先是将电脑上所有的盘符都查找出来,这里通过ctypes模块下来加载系统库文件来查询系统上存在的盘符,大家也是可以使用另外一些手段来获取系统上的盘符,我记得
还可以通过穷举的方式来将系统上的盘符列举出来,但是具体的实现我忘记了,这里就不多说了。
获取系统上盘符的代码如下:
def findDrive(): lpBuffer = ctypes.create_string_buffer(78) ctypes.windll.kernel32.GetLogicalDriveStringsA(ctypes.sizeof(lpBuffer),lpBuffer) vol = lpBuffer.raw.split('\x00') root = [] for i in vol: if i: root.append(i) return root
接下来就是功能函数的实现,主要的有两个函数,分别是:FileHasSuffix(包含有文件后缀的)和FileNoSuffix(不包含文件后缀),这两个函数是根据用户在输入
查询条件时是否有输入文件后缀名作为判断的依据。当用户没有输入文件后缀名,则会进入FileHasSuffix函数,然后做后续的工作;当用户没有输入文件后缀名时,
则会进入FileNoSuffix函数,然后做后续的工作。
FileHasSuffix函数的代码如下:
def FileHasSuffix(filepath,search,parameter,string): rule = '' # 用户填写了整个文件内容:文件名和后缀名 # 这样可以查找目录名和文件名为search或包含search的目录或文件 if parameter == '-f': filepath = filepath.split('\\')[-1] # 只是将文件的字串取出来做比较,这样保证了只比较文件名 filename = string[0] suffix = '.' + string[1] # 后缀名 rule = '.?' + filename + '.?' + suffix + '$' elif parameter == '-a': # 可以将目录包含有该字串的也显示出来 filename = string[0] suffix = '\.' + string[1] rule = '.*' + filename + '.*' + suffix + '$' return rule,filepath
FileHasSuffix函数传入的参数分别为:文件绝对路径、搜索条件、参数和一个列表,该列表就是保存有文件名和后缀名的列表,该函数主要的功能是将用户输入的
文件名和后缀名作为查找的条件。-f 是查找文件,如果输入的search条件为test.txt,那么就只搜索包含test文件名的文件并且后缀为txt的文件,如果是-a,则除了
-f外,还包含目录的查询,就是当有包含test字串的目录时,也是会将相应目录下的文件都列举出来的。
FileNoSuffix函数的代码如下:
def FileNoSuffix(filepath,search,parameter,string): rule = '' # 发生这个数组溢出异常,证明用户没有填写文件的后缀名 if parameter == '-f': # 当查询文件时,就将当前的filepath变为文件名,这样匹配的肯定是文件 # 只有该文件名的可以查找到 filepath = filepath.split('\\')[-1] rule = '.?' + search + '.?' + '\.\w+' # + 是一个或以上这些字符 elif parameter == '-h': # 以后缀名来查找文件 filepath = filepath.split('.')[-1] # 保证只取后缀名做比较 suffix = string[0] rule = suffix + '$' elif parameter == '-d': filepath = filepath[0:filepath.rindex('\\')] # 保证只比较目录字串 rule = '.*' + search + '.*' elif parameter == '-a': rule = '.*' + search + '.*' return rule,filepath
该函数传入的参数与FileHasSuffix函数的一样,只是这个函数多了两项功能而已,分别是-d(比较目录)和-h(比较文件后缀),-d就是查找目录中哪些是包含
有输入的字串的,找到后就会将相应目录下的文件都列举出来写进文档中。而-h参数,则主要是查找有相应后缀的文件,如果你想查找txt文件,那么就只需在函数
调用是输入该后缀并选择相应参数就可以啦,然后函数就会返回相应的正则表达死来给调用函数筛选文件,下面才调用这些函数来获取相应的文件。
ConditionsFind函数代码:
def ConditionsFind(filepath,search,parameter='-a'): if parameter == '-r': # 使用正则表达式查找 rule = search path = filepath else: string = search.split('.') rule = '' path = '' if len(string) > 1: rule,path = FileHasSuffix(filepath=filepath,search=search,parameter=parameter,string=string) else: rule,path = FileNoSuffix(filepath=filepath,search=search,parameter=parameter,string=string) result = re.search(rule,path) if result is not None: return True else: return False
这个函数中可以看到,传进的参数有三个,分别是:文件绝对路径、搜索条件和参数,这个函数的主要功能是判断该文件路径或目录路径是否符合搜索要求,还有
一个就是可以自己编写正则表达式来查找文件或目录。在这个函数中就对上述的两个函数进行调用了,在这个函数中并不是最终的调用函数,只是管理函数而已。
这个函数返回一个布尔值来用作最后的判断,判断的依据是根据正则表达式resule=re.search(rule,path)返回的结果,使用不同的正则表达式函数可能会有不同
的结果,具体就需要大家测试了。在这个函数中,大家还可以将所需要的功能函数扩展到这,然后添加相应的选项就可以扩展出所需的功能,至于要求怎样的功能,
那只能看你们怎么去实现了。
findFile函数代码如下:
def findFile(filepath,search,parameter,filename): count =0 dirThread = [] listFile = os.listdir(filepath) # listdir只是将当前目录下的文件或目录名列举出来,并包含有整个路径 # 打开文件,将其内容写进文件中 result = open('H:\\python\\working\\' + filename,'a') for file in listFile: count += 1 try: file =os.path.join(filepath,file) if os.path.isfile(file): print('.'), if count % 100 == 0: print else: findFile(file,search,parameter,filename) except WindowsError,e: print('WindowsError',e) # 查找到的文件 if ConditionsFind(file,search,parameter): result.write(file + '\n') result.close()
我想大家都知道这个是最终的调用函数了吧,这个函数主要是辨别当前路径是文件还是目录,如果是文件,则会将其路径传进ConditionsFind函数中,如果符合要求,
则将其文件路径写进文档中,该文档就是result文件流,文件名就是传进来的filename,至于路径大家自行修改,反之,查找下一个文件路径。
提示:这个函数的if os.path.isfile(file)语句块并没有实际的意义,只是简单的输入一个'.',用于确保程序是在执行中,并且可以标志文件的个数,但是当使用多线程
查询时,这样写会导致凌乱的输出,所以还应该在输出前对其进行加锁,输出完后解锁,这样才可以有序的输出。
注意:因为这函数中没有对保护的磁盘作判断,可能会导致花费的时间增加,大家或者可以将保护磁盘产生的异常捕获,然后跳过检查该磁盘的内容以免花销过大。
或者还可以尝试绕过保护系统的保护来获取访问磁盘驱动的权限。
最后,就是测试上述的代码:
if __name__ == '__main__': start = time.time() threadFind = [] root = findDrive() for drive in root: t = threading.Thread(target=findFile,args=(drive,'test.txt','-f','kkkk.doc')) threadFind.append(t) for t in threadFind: t.start() for t in threadFind: t.join() print('use time : %f second' %(time.time() - start))
这里采用了threading下的多线程函数来搜索文件,这里只是简单的将磁盘下的每个目录都是一个线程来查找,但是这种速度肯定不足以满足需求的,大家还可以通过
改变上述的代码来达到需求,比如:磁盘目录下的每个目录文件也是一个线程,那就是每个目录都是一个独立的线程;或者还可以采用多进程的方式来查找,进程还可以
包含更多的线程数,这样的速度应该能满足了。
运行上述的测试代码,测试效果如下:
保存文件路径的文档:
测试所需的时间,195s也是挺快的啊。
接下来会给大家带来使用其他的条件来进行查询文件。