2016-11-04 62 views
2

我需要掃描一個目錄,其中包含具有結構化部分(我想要掃描的)和非結構化部分(我不想掃描)的數百或GB數據。Python os.walk複雜目錄標準

閱讀os.walk函數,我發現我可以使用一組條件來排除或包含某些目錄名稱或模式。

對於這個特定的掃描,我需要添加特定的包含/排除每一級的標準目錄中的,例如:

在根目錄下,設想有兩種有用的目錄,「風向A」和「風向B'和一個無用的垃圾目錄'垃圾'。在方向A中有兩個有用的子目錄'Subdir A1'和'Subdir A2'以及一個無用的'SubdirA Trash'目錄,然後在方向B中有兩個有用的子目錄Subdir B1和Subdir B2加上一個無用的'SubdirB Trash'子目錄。會是這個樣子:

Example Directory

我需要爲每個級別一個具體的標準列表中,這樣的事情:

level1DirectoryCriteria =集( 「目錄A」, 「迪爾B」 )

level2DirectoryCriteria =集( 「子目錄A1」, 「A2子目錄」, 「子目錄 B1」, 「B2子目錄」)

我認爲這樣做的唯一方式顯然是非pythonic使用複雜和冗長的代碼與很多變量和高風險的不穩定。有沒有人有任何想法如何解決這個問題?如果成功,它可以一次保存幾個小時的代碼運行時間。

回答

2

你可以嘗試這樣的事:

to_scan = {'set', 'of', 'good', 'directories'} 
for dirpath, dirnames, filenames in os.walk(root): 
    dirnames[:] = [d for d in dirnames if d in to_scan] 
    #whatever you wanted to do in this directory 

這辦法很簡單,如果你想,如果他們出現在一個目錄,而不是另一個掃描目錄具有特定名稱失敗。另一種選擇是將目錄名稱映射到列表或一組白名單或黑名單目錄的字典。

編輯:我們可以使用dirpath.count(os.path.sep)來確定深度。

root_depth = root.count(os.path.sep) #subtract this from all depths to normalize root to 0 
sets_by_level = [{'root', 'level'}, {'one', 'deep'}] 
for dirpath, dirnames, filenames in os.walk(root): 
    depth = dirpath.count(os.path.sep) - root_depth 
    dirnames[:] = [d for d in dirnames if d in sets_by_level[depth]] 
    #process this directory 
+0

這看起來promising-我想出來,並會回來給你。 – user3535074

+1

解決方案來自於此! – user3535074

1

不涉及os.walk但只是一個建議直接回答:既然你反正掃描目錄,你明明知道從其他目錄垃圾桶目錄,你也可以把一個虛擬文件在垃圾桶目錄skip_this_dir什麼的。在迭代目錄並創建文件列表時,檢查skip_this_dir文件的存在,如if 'skip_this_dir' in filenames: continue;,並繼續下一次迭代。

這可能不涉及使用os.walk參數,但它確實使編程任務更容易管理,而無需編寫大量含有條件和包含/排除列表的「混亂」代碼。它還使腳本更易於重用,因爲您不需要更改任何代碼,只需將虛擬文件放在需要跳過的目錄中即可。

+0

這是一個好主意,但可能需要很長時間才能爲我不想掃描的目標添加跳過標誌。說我想掃描哪些目標,以及如果將來我需要添加一些目標,這相對容易一些。你雖然避免了複雜的代碼 - 我會記住你的建議。 – user3535074

+0

是的,如果你有很多垃圾目錄,把它們全部標記起來可能會很麻煩。你也可以通過標記你想要處理的dirs來推理,但我認爲你可能也有很多目錄需要處理。 – TBZ92

0

通過使用root.count(os.path.sep),我能夠在結構中的每個級別上包含/排除什麼內容創建具體說明。看起來像這樣:

import os 

root_depth = root.count(os.path.sep) #subtract this from all depths to normalize root to 0 

directoriesToIncludedByLevel = [{"criteriaString","criteriaString","criteriaString","criteriaString"},#Level 0 
           {"criteriaString","criteriaString","criteriaString" },#Level 1 
           {},#Level 2 
           ] 

directoriesToExcludedByLevel = [{}, #Level 0 
           {}, #Level 1 
           {"criteriaString"}, #Level 2 
           ] 


for dirpath, dirnames, filenames in os.walk(root): 

    depth = dirpath.count(os.path.sep) - root_depth 

    # Here we create the dirnames path depending on whether we use the directoriesToIncludedByLevel or the directoriesToExcludedByLevel 
    if depth == 2: #Where we define which directories to exclude 
     dirnames[:] = [d for d in dirnames if d not in directoriesToExcludedByLevel[depth]] 
    elif depth < 2 : #Where we define which directories to INclude 
     dirnames[:] = [d for d in dirnames if d in directoriesToIncludedByLevel[depth]] 
0

我正在尋找類似於OP的解決方案。我需要掃描子文件夾,並需要排除具有標籤爲「垃圾」的文件夾的任何文件夾。 我的解決方案是使用字符串find()方法。以下是我的使用方法:

for (dirpath, dirnames, filenames) in os.walk(your_path): 
    if dirpath.find('trash') > 0: 
     pass 
    elif dirpath.find('trash)') < 0: 
     do_stuff 

如果找到「垃圾箱」,則會返回索引號。否則find()將返回-1。

您可以找到find()方法在這裏更多的信息: https://www.tutorialspoint.com/python/string_find.htm