有没有办法在Python中返回当前目录中所有子目录的列表?
我知道您可以对文件执行此操作,但我需要获得目录列表。
有没有办法在Python中返回当前目录中所有子目录的列表?
我知道您可以对文件执行此操作,但我需要获得目录列表。
当前回答
谢谢你们的建议,伙计们。我遇到了软链接(无限递归)作为dirs返回的问题。Softlinks吗?我们不想要臭软链接!所以…
这只是渲染dirs,而不是软链接:
>>> import os
>>> inf = os.walk('.')
>>> [x[0] for x in inf]
['.', './iamadir']
其他回答
虽然这个问题很久以前就有答案了。我想推荐使用pathlib模块,因为这是在Windows和Unix操作系统上工作的一种健壮的方式。
要获取特定目录下的所有路径,包括子目录:
from pathlib import Path
paths = list(Path('myhomefolder', 'folder').glob('**/*.txt'))
# all sorts of operations
file = paths[0]
file.name
file.stem
file.parent
file.suffix
etc.
这应该可以工作,因为它还创建了一个目录树;
import os
import pathlib
def tree(directory):
print(f'+ {directory}')
print("There are " + str(len(os.listdir(os.getcwd()))) + \
" folders in this directory;")
for path in sorted(directory.glob('*')):
depth = len(path.relative_to(directory).parts)
spacer = ' ' * depth
print(f'{spacer}+ {path.name}')
这应该列出使用pathlib库的文件夹中的所有目录。path.relative_to(目录)。Parts获取相对于当前工作目录的元素。
最简单的方法:
from pathlib import Path
from glob import glob
current_dir = Path.cwd()
all_sub_dir_paths = glob(str(current_dir) + '/*/') # returns list of sub directory paths
all_sub_dir_names = [Path(sub_dir).name for sub_dir in all_sub_dir_paths]
比上面的要好得多,因为你不需要几个os.path.join(),你将直接获得完整的路径(如果你愿意的话),你可以在Python 3.5及以上版本中这样做。
subfolders = [ f.path for f in os.scandir(folder) if f.is_dir() ]
这将给出子目录的完整路径。 如果您只想要子目录的名称,请使用f.name而不是f.path
https://docs.python.org/3/library/os.html#os.scandir
稍微OT:如果你需要递归所有子文件夹和/或递归所有文件,看看这个函数,它比os更快。Walk & glob将返回所有子文件夹以及这些(子)子文件夹中的所有文件的列表:https://stackoverflow.com/a/59803793/2441026
如果你只需要递归的所有子文件夹:
def fast_scandir(dirname):
subfolders= [f.path for f in os.scandir(dirname) if f.is_dir()]
for dirname in list(subfolders):
subfolders.extend(fast_scandir(dirname))
return subfolders
返回所有子文件夹及其完整路径的列表。这个还是比os快。走,比glob快多了。
所有功能的分析
tl;博士: -如果你想获取一个文件夹的所有直接子目录,请使用os.scandir。 —如果您想获取所有子目录,甚至是嵌套的子目录,请使用os。行走或者——稍微快一点——上面的fast_scandir函数。 —不要使用操作系统。只遍历顶级子目录,因为它可能比os.scandir慢数百倍(!)。
If you run the code below, make sure to run it once so that your OS will have accessed the folder, discard the results and run the test, otherwise results will be screwed. You might want to mix up the function calls, but I tested it, and it did not really matter. All examples will give the full path to the folder. The pathlib example as a (Windows)Path object. The first element of os.walk will be the base folder. So you will not get only subdirectories. You can use fu.pop(0) to remove it. None of the results will use natural sorting. This means results will be sorted like this: 1, 10, 2. To get natural sorting (1, 2, 10), please have a look at https://stackoverflow.com/a/48030307/2441026
结果:
os.scandir took 1 ms. Found dirs: 439
os.walk took 463 ms. Found dirs: 441 -> it found the nested one + base folder.
glob.glob took 20 ms. Found dirs: 439
pathlib.iterdir took 18 ms. Found dirs: 439
os.listdir took 18 ms. Found dirs: 439
用W7x64测试,Python 3.8.1。
# -*- coding: utf-8 -*-
# Python 3
import time
import os
from glob import glob
from pathlib import Path
directory = r"<insert_folder>"
RUNS = 1
def run_os_walk():
a = time.time_ns()
for i in range(RUNS):
fu = [x[0] for x in os.walk(directory)]
print(f"os.walk\t\t\ttook {(time.time_ns() - a) / 1000 / 1000 / RUNS:.0f} ms. Found dirs: {len(fu)}")
def run_glob():
a = time.time_ns()
for i in range(RUNS):
fu = glob(directory + "/*/")
print(f"glob.glob\t\ttook {(time.time_ns() - a) / 1000 / 1000 / RUNS:.0f} ms. Found dirs: {len(fu)}")
def run_pathlib_iterdir():
a = time.time_ns()
for i in range(RUNS):
dirname = Path(directory)
fu = [f for f in dirname.iterdir() if f.is_dir()]
print(f"pathlib.iterdir\ttook {(time.time_ns() - a) / 1000 / 1000 / RUNS:.0f} ms. Found dirs: {len(fu)}")
def run_os_listdir():
a = time.time_ns()
for i in range(RUNS):
dirname = Path(directory)
fu = [os.path.join(directory, o) for o in os.listdir(directory) if os.path.isdir(os.path.join(directory, o))]
print(f"os.listdir\t\ttook {(time.time_ns() - a) / 1000 / 1000 / RUNS:.0f} ms. Found dirs: {len(fu)}")
def run_os_scandir():
a = time.time_ns()
for i in range(RUNS):
fu = [f.path for f in os.scandir(directory) if f.is_dir()]
print(f"os.scandir\t\ttook {(time.time_ns() - a) / 1000 / 1000 / RUNS:.0f} ms.\tFound dirs: {len(fu)}")
if __name__ == '__main__':
run_os_scandir()
run_os_walk()
run_glob()
run_pathlib_iterdir()
run_os_listdir()
你可以用glob。glob
from glob import glob
glob("/path/to/directory/*/", recursive = True)
不要忘记*后面的/。