关于python:os.walk没有深入到下面的目录

os.walk without digging into directories below

如何将os.walk限制为仅返回我提供的目录中的文件?

1
2
3
4
5
6
7
8
9
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


不要使用os.walk。

例:

1
2
3
4
5
6
import os

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


使用walklevel功能。

1
2
3
4
5
6
7
8
9
10
11
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
break

要只进行for循环的第一次迭代,必须有一种更优雅的方式。

1
2
3
4
5
6
for root, dirs, files in os.walk(dir_name):
    for f in files:
        ...
        ...
    break
...

第一次调用os.walk时,它返回当前目录的郁金香,然后在下一个循环中返回下一个目录的内容。

采用原始脚本,只需添加一个休息时间。

1
2
3
4
5
6
7
8
9
10
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


建议使用listdir是一个很好的建议。在Python 2中直接回答您的问题是root, dirs, files = os.walk(dir_name).next()

等效的Python 3语法是root, dirs, files = next(os.walk(dir_name))


您可以使用os.listdir()返回给定目录中的名称列表(对于文件和目录)。如果需要区分文件和目录,请在每个名称上调用os.stat()


如果您的要求比顶级目录更复杂(例如忽略VCS目录等),您还可以修改目录列表以防止os.walk通过它们进行递归。

即:

1
2
3
4
5
6
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
2
3
for path, dirs, files in os.walk('.'):
    print path, dirs, files
    del dirs[:] # go only one level deep


listdir相同的想法,但更短:

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


感觉好像扔了我的2便士。

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

在Python 3中,我能够做到这一点:

1
2
3
4
5
6
7
8
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] )


您还可以执行以下操作:

1
2
3
4
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


使用listdir时有一个问题。 os.path.isdir(标识符)必须是绝对路径。要选择子目录,您需要执行以下操作:

1
2
3
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()的情况下更改到目录以进行测试。


os.walk找到的每个目录的根文件夹更改。我解决了检查root ==目录的问题

1
2
3
4
5
6
7
8
9
10
def _dir_list(self, dir_name, whitelist):
    outputList = []
    for root, dirs, files in os.walk(dir_name):
        if root == dir_name: #This only meet parent folder
            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

您可以使用此代码段

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

创建一个排除列表,使用fnmatch跳过目录结构并执行该过程

1
2
3
4
5
6
7
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
            ....

与'includes'相同:

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

为什么不简单地使用rangeos.walk结合zip?不是最好的解决方案,但也会有效。

例如这样:

1
2
3
4
# your part before
for count, (root, dirs, files) in zip(range(0, 1), os.walk(dir_name)):
    # logic stuff
# your later part

在python 3上为我工作。

另外:A break比较简单。 (看看@Pieter的答案)


Alex的回答略有变化,但使用__next__()

print(next(os.walk('d:/'))[2])
要么
print(os.walk('d:/').__next__()[2])

[2]是其他答案中提到的root, dirs, file中的file


从Python 3.5开始,您可以使用os.scandir而不是os.listdir。而不是字符串,你得到一个DirEntry对象的迭代器作为回报。来自文档:

Using scandir() instead of listdir() can significantly increase the performance of code that also needs file type or file attribute information, because DirEntry objects expose this information if the operating system provides it when scanning a directory. All DirEntry methods may perform a system call, but is_dir() and is_file() usually only require a system call for symbolic links; DirEntry.stat() always requires a system call on Unix but only requires one for symbolic links on Windows.

您可以通过DirEntry.name访问对象的名称,然后等效于os.listdir的输出


这就是我解决它的方式

1
2
3
4
5
6
if recursive:
    items = os.walk(target_directory)
else:
    items = [next(os.walk(target_directory))]

...