2008-10-23 64 views
70

如何限制os.walk只返回我提供的目錄中的文件?os.walk無需挖掘到以下目錄

def _dir_list(self, dir_name, whitelist): 
    outputList = [] 
    for root, dirs, files in os.walk(dir_name): 
     for f in files: 
      if os.path.splitext(f)[1] in whitelist: 
       outputList.append(os.path.join(root, f)) 
      else: 
       self._email_to_("ignore") 
    return outputList 
+0

其中,與他們一起去可能的方法,所有的告誡衆人表明這種功能應該被加入到Python的另一種情況標準庫。 – antred 2016-10-31 19:26:09

回答

74

使用walklevel函數。

import os 

def walklevel(some_dir, level=1): 
    some_dir = some_dir.rstrip(os.path.sep) 
    assert os.path.isdir(some_dir) 
    num_sep = some_dir.count(os.path.sep) 
    for root, dirs, files in os.walk(some_dir): 
     yield root, dirs, files 
     num_sep_this = root.count(os.path.sep) 
     if num_sep + level <= num_sep_this: 
      del dirs[:] 

它的工作原理就像os.walk,但你可以傳遞一個level參數,指示遞歸將有多深。

+1

這個函數實際上是「遍歷」整個結構,然後刪除某個點下面的條目嗎?或者是更聰明的事情呢?我甚至不知道如何用代碼來檢查。 --python beginner – mathtick 2010-08-19 18:05:48

6

你可以使用os.listdir()返回名稱的列表(文件和目錄)在指定目錄。如果您需要區分文件和目錄,請在每個名稱上撥打os.stat()

154

請勿使用os.walk。

實施例:

import os 

root = "C:\\" 
for item in os.listdir(root): 
    if os.path.isfile(os.path.join(root, item)): 
     print item 
+5

這應該是被接受的答案... – 576i 2016-05-19 12:29:24

+1

@ 576i:這不區分文件和目錄 – Olexandr 2016-06-03 09:07:29

+0

@Alexandr`os.path.isfile`和`os.path.isdir`讓您區分。我不明白,因爲`'os.path.isfile`在'08之後就是示例代碼,而你的評論是'16'。這顯然是更好的答案,因爲你不打算走一個目錄,而是要列出它。 – 2017-08-29 08:17:38

14

使用listdir的建議是一個好。你的問題的直接答案是root, dirs, files = os.walk(dir_name).next()

+0

哦,我從那一個得到各種有趣的錯誤。 ValueError:打開太多的值 – Setori 2008-10-24 01:34:27

+0

不錯!雖然感覺像黑客。就像當你打開一個引擎,但只讓它進行一次革命,然後拉出鑰匙讓它死亡。 – 2017-08-29 08:24:12

8

如果你有比頂級目錄更復雜的要求(例如忽略VCS dirs等),你也可以修改目錄列表來防止os.walk遞歸遍歷它們。

即:

def _dir_list(self, dir_name, whitelist): 
    outputList = [] 
    for root, dirs, files in os.walk(dir_name): 
     dirs[:] = [d for d in dirs if is_good(d)] 
     for f in files: 
      do_stuff() 

注 - 要小心發生變異的名單,而不僅僅是重新綁定。 os.walk顯然不知道外部重新綁定。

+1

指出需要改變dirs! – darKoram 2012-11-20 22:43:11

1

你也可以做到以下幾點:

for path, subdirs, files in os.walk(dir_name): 
    for name in files: 
     if path == ".": #this will filter the files in the current directory 
      #code here 
22

我認爲解決的辦法其實很簡單。

使用

break 

只做for循環第一次迭代,必須有一個更優雅的方式。

for root, dirs, files in os.walk(dir_name): 
    for f in files: 
     ... 
     ... 
    break 
... 

調用os.walk第一次,它返回鬱金香當前目錄​​下,然後在下一循環的下一個目錄的內容。

以原始腳本,只需添加一個休息

def _dir_list(self, dir_name, whitelist): 
    outputList = [] 
    for root, dirs, files in os.walk(dir_name): 
     for f in files: 
      if os.path.splitext(f)[1] in whitelist: 
       outputList.append(os.path.join(root, f)) 
      else: 
       self._email_to_("ignore") 
     break 
    return outputList 
4

listdir同樣的想法,但更短:

[f for f in os.listdir(root_dir) if os.path.isfile(os.path.join(root_dir, f))] 
0

這是我如何解決它

if recursive: 
    items = os.walk(target_directory) 
else: 
    items = [next(os.walk(target_directory))] 

... 
0

使用listdir同時,當有一個陷阱。 os.path.isdir(標識符)必須是絕對路徑。要選擇子目錄你這樣做:

for dirname in os.listdir(rootdir): 
    if os.path.isdir(os.path.join(rootdir, dirname)): 
    print("I got a subdirectory: %s" % dirname) 

另一種方法是改變的目錄做的測試,而不os.path.join()。

2

在Python 3,我能做到這一點。

import os 
dir = "/path/to/files/" 

#List all files immediately under this folder: 
print (next(os.walk(dir))[2]) 

#List all folders immediately under this folder: 
print (next(os.walk(dir))[1]) 
4
for path, dirs, files in os.walk('.'): 
    print path, dirs, files 
    del dirs[:] # go only one level deep 
0

您可以使用此代碼段

for root, dirs, files in os.walk(directory): 
    if level > 0: 
     # do some stuff 
    else: 
     break 
    level-=1 
3

感覺自己就像扔我的2便士

baselevel = len(rootdir.split("\\")) 
for subdirs, dirs, files in os.walk(rootdir): 
    curlevel = len(subdirs.split("\\")) 
    if curlevel <= baselevel + 1: 
     [do stuff] 
0

創建排除列表,使用fnmatch跳過目錄結構和d執行過程

excludes= ['a\*\b', 'c\d\e'] 
for root, directories, files in os.walk('Start_Folder'): 
    if not any(fnmatch.fnmatch(nf_root, pattern) for pattern in excludes): 
     for root, directories, files in os.walk(nf_root): 
      .... 
      do the process 
      .... 

相同「包括」:

if **any**(fnmatch.fnmatch(nf_root, pattern) for pattern in **includes**):