PythonOS.walk到某个级别
我想建立一个程序,使用一些基本的代码来读取一个文件夹,并告诉我文件夹中有多少文件。 以下是我目前的做法:PythonOS.walk到某个级别,python,directory,subdirectory,python-os,Python,Directory,Subdirectory,Python Os,我想建立一个程序,使用一些基本的代码来读取一个文件夹,并告诉我文件夹中有多少文件。 以下是我目前的做法: import os folders = ['Y:\\path1', 'Y:\\path2', 'Y:\\path3'] for stuff in folders: for root, dirs, files in os.walk(stuff, topdown=True): print("there are", len(files), "files in", root
import os
folders = ['Y:\\path1', 'Y:\\path2', 'Y:\\path3']
for stuff in folders:
for root, dirs, files in os.walk(stuff, topdown=True):
print("there are", len(files), "files in", root)
在“主”文件夹中有多个文件夹之前,这种方法非常有效,因为由于文件夹/文件管理不善,它可能会返回一个长而无用的文件列表。所以我最多只想进入第二级。例如:
Main Folder
---file_i_want
---file_i_want
---Sub_Folder
------file_i_want <--*
------file_i want <--*
------Sub_Folder_2
---------file_i_dont_want
---------file_i_dont_want
但无论我如何寻找,我都无法找到如何深入两层。我可能只是不理解上面的其他帖子或者别的什么?我在想类似于del dirs[:2]的东西,但没有用。有人能指导我或向我解释如何做到这一点吗?你可以这样做:
depth = 2
# [1] abspath() already acts as normpath() to remove trailing os.sep
#, and we need ensures trailing os.sep not exists to make slicing accurate.
# [2] abspath() also make /../ and ////, "." get resolved even though os.walk can returns it literally.
# [3] expanduser() expands ~
# [4] expandvars() expands $HOME
stuff = os.path.abspath(os.path.expanduser(os.path.expandvars(stuff)))
for root,dirs,files in os.walk(stuff):
if root[len(stuff):].count(os.sep) < depth:
for f in files:
print(os.path.join(root,f))
注意:
os.listdir
和os.path.isfile
执行2个stat
调用,因此不是最优的。在Python3.5中,使用os.scandir
可以避免双重调用。可以计算分隔符,如果是两级深度,则删除dirs
的内容,这样walk
就不会在更深的层次上重复:
import os
MAX_DEPTH = 2
folders = ['Y:\\path1', 'Y:\\path2', 'Y:\\path3']
for stuff in folders:
for root, dirs, files in os.walk(stuff, topdown=True):
print("there are", len(files), "files in", root)
if root.count(os.sep) - stuff.count(os.sep) == MAX_DEPTH - 1:
del dirs[:]
说明以下行为:
当topdown为True时,调用方可以就地修改dirnames列表(可能使用del或slice赋值),walk()将只递归到名称保留在dirnames中的子目录中;这可以用于删除搜索、强制执行特定的访问顺序,甚至可以在再次恢复walk()之前通知walk()调用方创建或重命名的目录
请注意,您需要考虑
文件夹中存在的分隔符。例如,当运行y:\path1
时,根目录是y:\path
,但您不想在那里停止递归。dirs
是当前目录中的所有目录,它不是文件夹树的深度。@PeterWood,啊!这是有道理的。所以现在我明白了为什么deldirs[:2]
很愚蠢了……看起来您正在使用Python3。正确吗?@PM2Ring,正确。请注意,链接问题的公认答案中的代码也适用于Python 2,尽管问题的标题是。对于Python3的使用,可以使用yield from
而不是For
循环中的yield
语句来稍微清理它们。这就是我想要的。我真的很欣赏“关键是”的说法。如果你能解释一下或者给我指一些关于你是如何得出这个答案的文件?我一直在想为什么root[len(stuff…])
中的括号以及.count(os.sep)
的作用。非常感谢。为什么不在root[len(stuff)+1:://count(os.sep)时中断>=2
?当自上而下时,如果这是真的,则root
@DavidCullen的所有其他值都将是真的。没有想到这一点。实际上它不起作用,似乎只适用于目录。@MattR:我对字符串执行切片以删除第一个字符(对应于root
中stuff
的长度,然后我在以这种方式计算的相对路径上计算斜杠/反斜杠(依赖于操作系统:os.sep
)。@DavidCullen在以下设置中,这不是真的:x{a{1,2},b{1,2}
,元素顺序为:x
,x\a
,x\a\1
,x\a\2
,x\b
,x\b\1
,x\b\2
,因此,在找到第一个>2
时中断将意味着x\b
不会被重复。感谢您将我指向文档!是否正确de>root.count(os.sep)
正在计算根目录中的\
。@MattR:是的,它正在计算根目录中的\(或任何操作系统特定的分隔符),我们需要从中减去初始文件夹中的分隔符。由于这是以重复形式关闭的,您可能希望将答案发布到那里:
def scanrec(root):
rval = []
def do_scan(start_dir,output,depth=0):
for f in os.listdir(start_dir):
ff = os.path.join(start_dir,f)
if os.path.isdir(ff):
if depth<2:
do_scan(ff,output,depth+1)
else:
output.append(ff)
do_scan(root,rval,0)
return rval
print(scanrec(stuff)) # prints the list of files not below 2 deep
import os
MAX_DEPTH = 2
folders = ['Y:\\path1', 'Y:\\path2', 'Y:\\path3']
for stuff in folders:
for root, dirs, files in os.walk(stuff, topdown=True):
print("there are", len(files), "files in", root)
if root.count(os.sep) - stuff.count(os.sep) == MAX_DEPTH - 1:
del dirs[:]