如何在Python中获取所有直接子目录

时间:2009-04-28 22:59:12

标签: python file

我正在尝试编写一个简单的Python脚本,它将index.tpl复制到所有子目录中的index.html(除了少数例外)。

我试图获取子目录列表而陷入困境。

15 个答案:

答案 0 :(得分:196)

import os
def get_immediate_subdirectories(a_dir):
    return [name for name in os.listdir(a_dir)
            if os.path.isdir(os.path.join(a_dir, name))]

答案 1 :(得分:64)

为什么没有人提到globglob允许您使用Unix风格的路径名扩展,并且几乎可以找到需要查找多个路径名的所有内容。这很容易:

from glob import glob
paths = glob('*/')

请注意glob将返回带有最终斜杠的目录(如unix所示),而大多数基于path的解决方案将省略最终斜杠。

答案 2 :(得分:63)

我对各种功能进行了速度测试,以将完整路径返回到所有当前子目录。

tl; dr: 始终使用scandir

list_subfolders_with_paths = [f.path for f in os.scandir(path) if f.is_dir()]

奖金:使用scandir,您也可以只使用f.name而不是f.path来获取文件夹名称。

此(以及下面的所有其他功能)将不使用自然排序。这意味着将对结果进行如下排序:1、10、2。要进行自然排序(1、2、10),请查看https://stackoverflow.com/a/48030307/2441026




结果scandir是:比walk快3倍,比listdir快32倍(带过滤器),比Pathlib快35倍,比listdir快36倍,以及37倍(! )比glob快。

Scandir:           0.977
Walk:              3.011
Listdir (filter): 31.288
Pathlib:          34.075
Listdir:          35.501
Glob:             36.277

在W7x64和Python 3.8.1中进行了测试。带有440个子文件夹的文件夹。
如果您想知道是否可以通过不两次执行os.path.join()来加快listdir的速度,可以,但是基本上没有区别。

代码:

import os
import pathlib
import timeit
import glob

path = r"<example_path>"



def a():
    list_subfolders_with_paths = [f.path for f in os.scandir(path) if f.is_dir()]
    # print(len(list_subfolders_with_paths))


def b():
    list_subfolders_with_paths = [os.path.join(path, f) for f in os.listdir(path) if os.path.isdir(os.path.join(path, f))]
    # print(len(list_subfolders_with_paths))


def c():
    list_subfolders_with_paths = []
    for root, dirs, files in os.walk(path):
        for dir in dirs:
            list_subfolders_with_paths.append( os.path.join(root, dir) )
        break
    # print(len(list_subfolders_with_paths))


def d():
    list_subfolders_with_paths = glob.glob(path + '/*/')
    # print(len(list_subfolders_with_paths))


def e():
    list_subfolders_with_paths = list(filter(os.path.isdir, [os.path.join(path, f) for f in os.listdir(path)]))
    # print(len(list(list_subfolders_with_paths)))


def f():
    p = pathlib.Path(path)
    list_subfolders_with_paths = [x for x in p.iterdir() if x.is_dir()]
    # print(len(list_subfolders_with_paths))



print(f"Scandir:          {timeit.timeit(a, number=1000):.3f}")
print(f"Listdir:          {timeit.timeit(b, number=1000):.3f}")
print(f"Walk:             {timeit.timeit(c, number=1000):.3f}")
print(f"Glob:             {timeit.timeit(d, number=1000):.3f}")
print(f"Listdir (filter): {timeit.timeit(e, number=1000):.3f}")
print(f"Pathlib:          {timeit.timeit(f, number=1000):.3f}")

答案 3 :(得分:22)

检查&#34; Getting a list of all subdirectories in the current directory&#34;。

这是一个Python 3版本:

import os

dir_list = next(os.walk('.'))[1]

print(dir_list)

答案 4 :(得分:18)

import os, os.path

获取目录中的(完整路径)直接子目录:

def SubDirPath (d):
    return filter(os.path.isdir, [os.path.join(d,f) for f in os.listdir(d)])

获取最新(最新)子目录:

def LatestDirectory (d):
    return max(SubDirPath(d), key=os.path.getmtime)

答案 5 :(得分:11)

在这种情况下,

os.walk是你的朋友。

直接来自文档:

  

walk()通过从上到下或向下走树来生成目录树中的文件名。对于以目录top(包括top本身)为根的树中的每个目录,它会产生一个3元组(dirpath,dirnames,filenames)。

答案 6 :(得分:9)

这种方法可以一气呵成。

from glob import glob
subd = [s.rstrip("/") for s in glob(parent_dir+"*/")]

答案 7 :(得分:7)

使用Twisted的FilePath模块:

from twisted.python.filepath import FilePath

def subdirs(pathObj):
    for subpath in pathObj.walk():
        if subpath.isdir():
            yield subpath

if __name__ == '__main__':
    for subdir in subdirs(FilePath(".")):
        print "Subdirectory:", subdir

由于一些评论者已经问过使用Twisted库的优点是什么,我将在这里略微超出原来的问题。


分支中有some improved documentation解释了FilePath的优点;你可能想读一读。

更具体地说,在此示例中:与标准库版本不同,此功能可以使用 no imports 实现。 “subdirs”函数是完全通用的,因为它只对其参数进行操作。要使用标准库复制和移动文件,您需要依赖“open”内置,“listdir”,可能是“isdir”或“{{1} }“或”os.walk“。也许“shutil.copy”。更不用说你需要一个传递参数的字符串来识别实际文件。让我们看看将每个目录的“index.tpl”复制到“index.html”的完整实现:​​

os.path.join

上面的“subdirs”函数可以在任何类似def copyTemplates(topdir): for subdir in subdirs(topdir): tpl = subdir.child("index.tpl") if tpl.exists(): tpl.copyTo(subdir.child("index.html")) 的对象上运行。除其他外,这意味着FilePath个对象。不幸的是ZipPath现在是只读的,但它可以扩展为支持写作。

您也可以传递自己的对象以进行测试。为了测试这里建议的os.path-using API,你必须使用导入的名称和隐式依赖项,并且通常执行黑魔法以使测试工作。使用FilePath,您可以执行以下操作:

ZipPath

答案 8 :(得分:3)

我刚刚编写了一些代码来移动vmware虚拟机,最后使用os.pathshutil来完成子目录之间的文件复制。

def copy_client_files (file_src, file_dst):
    for file in os.listdir(file_src):
            print "Copying file: %s" % file
            shutil.copy(os.path.join(file_src, file), os.path.join(file_dst, file))

它不是非常优雅,但确实有效。

答案 9 :(得分:1)

这是一种方式:

import os
import shutil

def copy_over(path, from_name, to_name):
  for path, dirname, fnames in os.walk(path):
    for fname in fnames:
      if fname == from_name:
        shutil.copy(os.path.join(path, from_name), os.path.join(path, to_name))


copy_over('.', 'index.tpl', 'index.html')

答案 10 :(得分:0)

def get_folders_in_directories_recursively(self, directory, index=0):
    folder_list = list()
    parent_directory = directory

    for path, subdirs, _ in os.walk(directory):
        if not index:
            for sdirs in subdirs:
                folder_path = "{}/{}".format(path, sdirs)
                folder_list.append(folder_path)
        elif path[len(parent_directory):].count('/') + 1 == index:
            for sdirs in subdirs:
                folder_path = "{}/{}".format(path, sdirs)
                folder_list.append(folder_path)

    return folder_list

以下功能可以称为:

get_folders_in_directories_recursively(目录,索引= 1)->给出第一级文件夹列表

get_folders_in_directories_recursively(目录)->给出所有子文件夹

答案 11 :(得分:0)

import glob
import os

def child_dirs(path):
     cd = os.getcwd()        # save the current working directory
     os.chdir(path)          # change directory 
     dirs = glob.glob("*/")  # get all the subdirectories
     os.chdir(cd)            # change directory to the script original location
     return dirs

child_dirs函数在目录中获取路径,并在其中返回立即子目录的列表。

dir
 |
  -- dir_1
  -- dir_2

child_dirs('dir') -> ['dir_1', 'dir_2']

答案 12 :(得分:0)

我不得不提到我经常使用的path.py库。

获取直接子目录变得如此简单:

my_dir.dirs()

完整的工作示例是:

from path import Path

my_directory = Path("path/to/my/directory")

subdirs = my_directory.dirs()
  

注意:my_directory仍然可以作为字符串进行操作,因为Path是字符串的子类,但是提供了许多有用的方法来处理路径

答案 13 :(得分:0)

import pathlib


def list_dir(dir):
    path = pathlib.Path(dir)
    dir = []
    try:
        for item in path.iterdir():
            if item.is_dir():
                dir.append(item)
        return dir
    except FileNotFoundError:
        print('Invalid directory')

答案 14 :(得分:0)

使用pathlib的一个班轮:

list_subfolders_with_paths = [p for p in pathlib.Path(path).iterdir() if p.is_dir()]