Python遞迴遍歷目錄下所有檔案查詢指定檔案
之前看到網上有人說『os.path.isdir()判斷必須寫絕對路徑』,當時心想Python不是有迭代上下文嗎,為什麼不行?遂作本文驗證之
程式碼部分
考慮用一個path
變數指代當前遍歷元素的絕對路徑
(正確做法)
def search(root, target):
items = os.listdir(root)
for item in items:
path = os.path.join(root, item)
if os.path.isdir(path):
print('[-]', path)
search(path, target)
elif path.split('/')[-1] == target:
print('[+]', path)
else:
print('[!]', path)
正常遍歷的結果
如果這樣寫,把路徑全部換成item
(迭代元素)
def search(root, target):
items = os.listdir(root)
for item in items:
if os.path.isdir(item):
print('[-]', item)
search(os.path.join(root, item), target)
elif item == target:
print('[+]', os.path.join(root,item))
else:
print('[!]', os.path.join(root, item))
可以看出,這是行不通的:如果使用item
迭代元素進行指代當前路徑,最多隻會再往下遞迴兩層(子資料夾、子資料夾的檔案),可見所未的上下文管理機制在這裡是完全不起作用的
反思和總結
1)如果在正確遍歷寫法基礎上,僅改變每次遞迴時的傳遞元素迭代機制會做出怎樣的反應?
在上面的例子中,只需要把search(os.path.join(root, item), target)
search(item, target)
即可:
這一點很容易看出,因為在首次呼叫search(..)
函式時就是傳入了一個絕對路徑,如果傳入相對路徑因為沒有上下文環境,是不能正確定位檔案位置的
2)os.path.abspath(path)
方法可以替代os.path.join(root, current)
嗎?
實踐出真知:
(大霧)原來os.path.abspath(..)
表示的是:相對當前工作目錄的相對路徑!(而不是相對系統根目錄的相對路徑!)
所以,os.path.abspath(..)
和os.path.join(..)
是兩個完全不同的東西,是不能替換的
3)Python的檔案到底是什麼呢?
還是那份正確的程式碼,將每一條輸出改成用type(..)
函式包裹的形式
在看下面另一個例子
本著Python中『一切皆物件』的信念,我們輸入的路徑(包括它的迭代版本、用來接受它的變數)是一個字串str
物件,而用來描述檔案的檔案控制代碼(指標)則是一個_io.TextIOWrapper
型別的物件
通常我們在資料夾、檔案水平查詢、篩選,用的是str
型別的路徑描述,而要對具體某個檔案(不是資料夾)進行讀或寫的操作,就要用到_io.TextIOWrapper
型別的檔案控制代碼,它們分的比較細;不像Java中完全被封裝成了一個File(String path)
物件,它弱化了檔案路徑的作為單獨個體的作用——但是Python則把路徑單獨拎出來,我們很多的檔案操作(廣義上比如查詢指定檔案,不單指檔案IO),都是建立在檔案路徑的基礎上的
4)思考:除了開頭給出的方法,有沒有別的遍歷檔案辦法?
答案是:有的(yes)
os.chdir(path)
函式可以改變當前工作目錄到指定path
但是我們不推薦使用該方法,因為它修改了全域性變數,這一點在函式呼叫前後使用os.getcwd()
函式進行驗證
先把工作目錄切換到根目錄下,接著執行自定義的change()
函式
如你所見,這時候全域性的當前工作目錄
已經發生了改變