Python學習筆記之os.walk()函式
阿新 • • 發佈:2019-01-03
我們使用os,listdir()函式來列出目錄下的所有檔案和目錄放入一個列表進行返回,但是listdir()函式不可對目錄的子目錄進行掃描。
print(os.listdir('/'))
輸出:
['boot', 'dev', 'home', 'proc', 'run', 'sys', 'etc', 'root', 'var', 'tmp', 'usr', 'bin', 'sbin', 'lib', 'lib64', 'media', 'mnt', 'opt', 'srv', 'iso', 'redhat7.4-mount', '.autorelabel', 'directory', 'python']
很多時候我們需要將某個資料夾下的所有檔案都要找出來,那麼此時我們就需要os.walk()函式。os.walk()方法用於通過在目錄了數中向下或向上遊走,輸出目錄的檔名,該方法回訪回一個生成器。
os.walk(top[, topdown=True[, onerror=None[, followlinks=False]]])
top -- 是你所要遍歷的目錄的地址. topdown -- 可選,為 True,則優先遍歷top目錄, 否則優先遍歷 top 的子目錄(預設為開啟)。 onerror -- 可選,需要一個 callable 物件,當 walk 需要異常時,會呼叫。 followlinks -- 可選,如果為 True,則會遍歷目錄下的快捷方式,預設開啟 return None 該函式沒有返回值會使用yield關鍵字丟擲一個存放當前 該層目錄(root,dirs,files)的三元組,最終將所有目錄層的的結果變為一個生成器 root 所指的是當前正在遍歷的這個資料夾的本身的地址 dirs 是一個 list ,內容是該資料夾中所有的目錄的名字(不包括子目錄) files 同樣是 list , 內容是該資料夾中所有的檔案(不包括子目錄)
為了方便我們理解os.walk()最終丟擲的資料的型別我們對它的生成器進行強制轉換為list(),這樣我們就可以看出其內部資料結構。
在我們的/mnt下有下面幾個檔案和目錄
print(list(os.walk('/mnt',topdown = False)))
輸出:[('/mnt', ['dira', 'dirb'], ['file1', 'file2']), ('/mnt/dira', [], ['file_test_A']), ('/mnt/dirb', [], ['file_test_B'])]
這個列表(因為我們將生成器強制轉化為列表)中的每一個元素都是一個元組,每一個元組都是都是一層目錄,元組中的元素又代表了當前目錄層的路徑(根據賦給形參top的值來決定是絕對路徑還是相對路徑)、當前目錄下有的檔案目錄、和當前目錄下的檔案。當我們對生成器使用for迴圈時,會將每層一目錄資訊返回。
for info in os.walk('/mnt', topdown=True):
print(info)
print('***分隔符***')
輸出:
('/mnt', ['dira', 'dirb'], ['file1', 'file2'])
***分隔符***
('/mnt/dira', [], ['file_test_A'])
***分隔符***
('/mnt/dirb', [], ['file_test_B'])
***分隔符***
注意:
這裡丟擲的值檔案、路徑和資料夾是分離的而不是在一起的 使用檔案的據對路徑一定要root+os.path.sep+filenames
下面兩段程式碼就是我入過的坑
錯誤:
import os
def SearchAbsPath(dirname):
dirname = os.path.abspath(dirname)
filenames = list()
for root,dirs,files in os.walk(dirname, topdown=False): #掃描一層目錄
for name in files:
filenames.append(dirname+os.path.sep+name) #每一個檔案的絕對路徑放入列表
print(dirname+os.path.sep+name)
return filenames
SearchAbsPath('/mnt')
輸出:
/mnt/file_test_A
/mnt/file_test_B
/mnt/__init__.py
/mnt/file1
/mnt/file2
正確:
import os
def SearchAbsPath(dirname):
dirname = os.path.abspath(dirname)
filenames = list()
for root,dirs,files in os.walk(dirname, topdown=False): #掃描一層目錄
for name in files:
filenames.append(root+os.path.sep+name) #每一個檔案的絕對路徑放入列表
print(root+os.path.sep+name)
return filenames
SearchAbsPath('.')
輸出:
/mnt/dira/file_test_A
/mnt/dirb/file_test_B
/mnt/packeage/__init__.py
/mnt/file1
/mnt/file2
錯誤的程式碼,檔案絕對路徑=形參top的絕對路徑+os.path.sep+檔名, 因此當我們們的top目錄下還有多層目錄時,我們水價格中間目錄缺少,導致檔案據對路徑錯誤。
正確的程式碼,檔案絕對路徑 =root(在os.walk()傳入的引數時絕對路徑,root也就是絕對路徑)+os.path.sep+檔名,不會缺失中間目錄