120

如何限制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
4

21 回答 21

229

不要使用 os.walk。

例子:

import os

root = "C:\\"
for item in os.listdir(root):
    if os.path.isfile(os.path.join(root, item)):
        print item
于 2008-10-23T10:15:38.907 回答
111

使用该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参数来指示递归的深度。

于 2008-10-24T16:46:02.707 回答
59

我认为解决方案实际上非常简单。

采用

break

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

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

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

获取原始脚本并添加一个break

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
于 2014-01-01T12:44:22.767 回答
25

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

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

于 2008-10-23T10:46:22.620 回答
14

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

于 2008-10-23T10:06:02.450 回答
9

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

IE:

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 不知道外部重新绑定。

于 2008-10-23T10:49:05.220 回答
7
for path, dirs, files in os.walk('.'):
    print path, dirs, files
    del dirs[:] # go only one level deep
于 2016-05-03T15:43:13.630 回答
4

与 相同的想法listdir,但更短:

[f for f in os.listdir(root_dir) if os.path.isfile(os.path.join(root_dir, f))]
于 2014-06-25T20:38:16.873 回答
4

感觉就像把我的 2 便士扔进去一样。

baselevel = len(rootdir.split("\\"))
for subdirs, dirs, files in os.walk(rootdir):
    curlevel = len(subdirs.split("\\"))
    if curlevel <= baselevel + 1:
        [do stuff]
于 2017-06-02T08:14:38.033 回答
4

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

使用scandir()而不是listdir()可以显着提高还需要文件类型或文件属性信息的代码的性能,因为DirEntry如果操作系统在扫描目录时提供这些信息,对象就会公开这些信息。所有DirEntry方法都可以执行系统调用,但is_dir()通常is_file()只需要对符号链接进行系统调用;DirEntry.stat()在 Unix 上总是需要一个系统调用,但在 Windows 上只需要一个用于符号链接。

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

于 2019-05-27T12:15:54.470 回答
2

您还可以执行以下操作:

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
于 2012-10-18T23:15:07.673 回答
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] )
于 2016-04-01T14:13:41.290 回答
1
import os

def listFiles(self, dir_name):
    names = []
    for root, directory, files in os.walk(dir_name):
        if root == dir_name:
            for name in files:
                names.append(name)
    return names
于 2019-09-30T17:09:40.043 回答
0

这就是我解决它的方法

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

...
于 2015-01-06T17:47:02.483 回答
0

使用 listdir 时有一个问题。os.path.isdir(identifier) 必须是绝对路径。要选择您执行的子目录:

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() 的情况下进行测试。

于 2015-09-23T18:42:26.563 回答
0

您可以使用此代码段

for root, dirs, files in os.walk(directory):
    if level > 0:
        # do some stuff
    else:
        break
    level-=1
于 2016-08-24T08:56:51.557 回答
0

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

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**):
于 2017-11-21T09:49:23.500 回答
0

为什么不简单地使用 arange并与os.walk结合zip?不是最好的解决方案,但也可以。

例如像这样:

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

在 python 3 上为我工作。

另外:break顺便说一句,A 也更简单。(看@Pieter的答案)

于 2018-11-29T21:18:20.723 回答
0

亚历克斯的答案略有变化,但使用__next__()

print(next(os.walk('d:/'))[2]) 或者 print(os.walk('d:/').__next__()[2])

在其他答案[2]中提到fileroot, dirs, file

于 2019-01-30T13:59:55.777 回答
0

os.walk 找到的每个目录的根文件夹都会更改。我求解检查是否 root == 目录

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
于 2019-06-05T15:31:04.850 回答
0

这是一个很好的python示例

def walk_with_depth(root_path, depth):
        if depth < 0:
            for root, dirs, files in os.walk(root_path):
                yield [root, dirs[:], files]

            return

        elif depth == 0:
            return

        base_depth = root_path.rstrip(os.path.sep).count(os.path.sep)
        for root, dirs, files in os.walk(root_path):
            yield [root, dirs[:], files]

            cur_depth = root.count(os.path.sep)
            
            if base_depth + depth <= cur_depth:
                del dirs[:]
于 2020-12-23T07:44:32.123 回答