Python小技巧|如何在win系統下快速查找文件
在工作的時候有時需要去處理一些文件,如果不在一個文件夾里面會去遍歷整個盤符(如F盤),這個時候手動查找和搜索顯得非常慢,單個還好,如果多個,就不得不寫程序來處理了。

據我所知,Python有兩個函數可以遍歷文件夾(包括子文件夾),os模塊的walk函數,以及glob模塊的glob函數,其中os.walk函數,查看help文檔有示例代碼:
import os
from os.path import join, getsize
for root, dirs, files in os.walk('python/Lib/email'):
print(root, "consumes", end="")
print(sum([getsize(join(root, name)) for name in files]), end="")
print("bytes in", len(files), "non-directory files")
if 'CVS' in dirs:
dirs.remove('CVS') # don't visit CVS directories
可以直接拿來用,而glob.glob函數雖然沒提供示例,但help文檔也很清晰:
glob(pathname, *, recursive=False)
Return a list of paths matching a pathname pattern.
The pattern may contain simple shell-style wildcards a la
fnmatch. However, unlike fnmatch, filenames starting with a
dot are special cases that are not matched by '*' and '?'
patterns.
If recursive is true, the pattern '**' will match any files and
zero or more directories and subdirectories.
不難理解,第二個參數為**,且第三個參數為recursive=True時,即可以遍歷指定的路徑(包含子文件夾):
glob(pathname, **, recursive=True)
但是很遺憾的是,這兩個函數在遍歷文件和子文件夾比較多的文件夾時,會顯非常慢,如果你使用的是 win系統,則可以嘗試另外的方式。
很多朋友應該聽過?Everything 這個查找神器,-:
https://www.voidtools.com/zh-cn/downloads/
它在win系統下搜索文件可以說非常的快速,更多介紹請看這里:
https://www.voidtools.com/zh-cn/faq/
那怎么寫程序來調用呢?它提供了SDK:
http://www.voidtools.com/support/everything/sdk/
函數非常的多,也給了Python的調用示例:
import ctypes
import datetime
import struct
#defines
EVERYTHING_REQUEST_FILE_NAME = 0x00000001
EVERYTHING_REQUEST_PATH = 0x00000002
EVERYTHING_REQUEST_FULL_PATH_AND_FILE_NAME = 0x00000004
EVERYTHING_REQUEST_EXTENSION = 0x00000008
EVERYTHING_REQUEST_SIZE = 0x00000010
EVERYTHING_REQUEST_DATE_CREATED = 0x00000020
EVERYTHING_REQUEST_DATE_MODIFIED = 0x00000040
EVERYTHING_REQUEST_DATE_ACCESSED = 0x00000080
EVERYTHING_REQUEST_ATTRIBUTES = 0x00000100
EVERYTHING_REQUEST_FILE_LIST_FILE_NAME = 0x00000200
EVERYTHING_REQUEST_RUN_COUNT = 0x00000400
EVERYTHING_REQUEST_DATE_RUN = 0x00000800
EVERYTHING_REQUEST_DATE_RECENTLY_CHANGED = 0x00001000
EVERYTHING_REQUEST_HIGHLIGHTED_FILE_NAME = 0x00002000
EVERYTHING_REQUEST_HIGHLIGHTED_PATH = 0x00004000
EVERYTHING_REQUEST_HIGHLIGHTED_FULL_PATH_AND_FILE_NAME = 0x00008000
#dll imports
everything_dll = ctypes.WinDLL ("C:\EverythingSDK\DLL\Everything32.dll")
everything_dll.Everything_GetResultDateModified.argtypes = [ctypes.c_int,ctypes.POINTER(ctypes.c_ulonglong)]
everything_dll.Everything_GetResultSize.argtypes = [ctypes.c_int,ctypes.POINTER(ctypes.c_ulonglong)]
#setup search
everything_dll.Everything_SetSearchW("test.py")
everything_dll.Everything_SetRequestFlags(EVERYTHING_REQUEST_FILE_NAME | EVERYTHING_REQUEST_PATH | EVERYTHING_REQUEST_SIZE | EVERYTHING_REQUEST_DATE_MODIFIED)
#execute the query
everything_dll.Everything_QueryW(1)
#get the number of results
num_results = everything_dll.Everything_GetNumResults()
#show the number of results
print("Result Count: {}".format(num_results))
#convert a windows FILETIME to a python datetime
#https://stackoverflow.com/questions/39481221/convert-datetime-back-to-windows-64-bit-filetime
WINDOWS_TICKS = int(1/10**-7) # 10,000,000 (100 nanoseconds or .1 microseconds)
WINDOWS_EPOCH = datetime.datetime.strptime('1601-01-01 00:00:00',
'%Y-%m-%d %H:%M:%S')
POSIX_EPOCH = datetime.datetime.strptime('1970-01-01 00:00:00',
'%Y-%m-%d %H:%M:%S')
EPOCH_DIFF = (POSIX_EPOCH - WINDOWS_EPOCH).total_seconds() # 11644473600.0
WINDOWS_TICKS_TO_POSIX_EPOCH = EPOCH_DIFF * WINDOWS_TICKS # 116444736000000000.0
def get_time(filetime):
"""Convert windows filetime winticks to python datetime.datetime."""
winticks = struct.unpack(' microsecs = (winticks - WINDOWS_TICKS_TO_POSIX_EPOCH) / WINDOWS_TICKS return datetime.datetime.fromtimestamp(microsecs) #create buffers filename = ctypes.create_unicode_buffer(260) date_modified_filetime = ctypes.c_ulonglong(1) file_size = ctypes.c_ulonglong(1) #show results for i in range(num_results): everything_dll.Everything_GetResultFullPathNameW(i,filename,260) everything_dll.Everything_GetResultDateModified(i,date_modified_filetime) everything_dll.Everything_GetResultSize(i,file_size) print("Filename: {}\nDate Modified: {}\nSize: {} bytes\n".format(ctypes.wstring_at(filename),get_time(date_modified_filetime),file_size.value)) 顯得比較難以理解,我自己照著其他的示例寫了個簡單易理解的,代碼如下: from ctypes import windll,byref,create_unicode_buffer def search_files(file): Search = windll.LoadLibrary("everything64.dll") strBuff = create_unicode_buffer(255) Search.Everything_SetSearchW(file) Search.Everything_QueryW(True) Results = Search.Everything_GetNumResults() for index in range(Results): Search.Everything_GetResultFullPathNameW(index,byref(strBuff),len(strBuff)) yield strBuff.value del Search del strBuff if __name__=='__main__': for?file?in?search_files('*.py'): print (file) 在調用它的SDK時,網站上也很貼心的給了我們一些注意事項: 簡而言之就是在調用的時候,一定要打開?Everything 這個軟件。更多的功能請自己去發現吧^_^ Python
版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。
版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。