我正在尝试编写一个简单的Python脚本,它将index.tpl复制到所有子目录中的index.html(除了少数例外)。
我试图获取子目录列表而陷入困境。
答案 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)
为什么没有人提到glob
? glob
允许您使用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.path
和shutil
来完成子目录之间的文件复制。
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()]