python os.walk 到一定程度
python os.walk to certain level
我想构建一个程序,使用一些基本代码来读取文件夹并告诉我文件夹中有多少文件。
这是我目前的做法:
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" 文件夹中有多个文件夹之前,这非常有用,因为它可以 return 由于 folder/file 管理不善而导致的冗长的垃圾文件列表。所以我想最多只去二级。示例:
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
我知道如何使用 break
和取自 this post and also this post 的 del dirs[:]
仅进入第一级。
import os
import pandas as pd
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)
del dirs[:] # or a break here. does the same thing.
但无论我如何搜索,我都找不到如何深入两层。我可能只是不理解上面的其他帖子之类的?我在想 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
# WARN: Don't use [3] expanduser and [4] expandvars if stuff contains arbitrary string out of your control.
#stuff = os.path.expanduser(os.path.expandvars(stuff)) # if trusted source
stuff = os.path.abspath(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))
关键是:if root[len(stuff):].count(os.sep) < depth
它从 root
中删除了 stuff
,因此结果是相对于 stuff
的。只需计算文件分隔符的数量。
深度类似于 Linux 中的 find
命令,即 -maxdepth 0
表示什么都不做,-maxdepth 1
仅在第一级扫描文件,-maxdepth 2
扫描文件包含子目录。
当然,它仍然会扫描完整的文件结构,但除非它非常深,否则它会起作用。
另一种解决方案是只递归地使用 os.listdir
(通过目录检查)最大递归级别,但如果您不需要它,那会有点棘手。因为它并不难,这里有一个实现:
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
注意:os.listdir
和 os.path.isfile
执行 2 stat
次调用,因此不是最优的。在 Python 3.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[:]
Python documentation 声明以下行为:
When topdown is True, the caller can modify the dirnames list in-place (perhaps using del or slice assignment), and walk() will only recurse into the subdirectories whose names remain in dirnames; this can be used to prune the search, impose a specific order of visiting, or even to inform walk() about directories the caller creates or renames before it resumes walk() again.
请注意,您需要考虑 folders
中存在的分隔符。例如,当 y:\path1
被遍历根是 y:\path
但你不想在那里停止递归。
我想构建一个程序,使用一些基本代码来读取文件夹并告诉我文件夹中有多少文件。 这是我目前的做法:
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" 文件夹中有多个文件夹之前,这非常有用,因为它可以 return 由于 folder/file 管理不善而导致的冗长的垃圾文件列表。所以我想最多只去二级。示例:
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
我知道如何使用 break
和取自 this post and also this post 的 del dirs[:]
仅进入第一级。
import os
import pandas as pd
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)
del dirs[:] # or a break here. does the same thing.
但无论我如何搜索,我都找不到如何深入两层。我可能只是不理解上面的其他帖子之类的?我在想 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
# WARN: Don't use [3] expanduser and [4] expandvars if stuff contains arbitrary string out of your control.
#stuff = os.path.expanduser(os.path.expandvars(stuff)) # if trusted source
stuff = os.path.abspath(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))
关键是:if root[len(stuff):].count(os.sep) < depth
它从 root
中删除了 stuff
,因此结果是相对于 stuff
的。只需计算文件分隔符的数量。
深度类似于 Linux 中的 find
命令,即 -maxdepth 0
表示什么都不做,-maxdepth 1
仅在第一级扫描文件,-maxdepth 2
扫描文件包含子目录。
当然,它仍然会扫描完整的文件结构,但除非它非常深,否则它会起作用。
另一种解决方案是只递归地使用 os.listdir
(通过目录检查)最大递归级别,但如果您不需要它,那会有点棘手。因为它并不难,这里有一个实现:
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
注意:os.listdir
和 os.path.isfile
执行 2 stat
次调用,因此不是最优的。在 Python 3.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[:]
Python documentation 声明以下行为:
When topdown is True, the caller can modify the dirnames list in-place (perhaps using del or slice assignment), and walk() will only recurse into the subdirectories whose names remain in dirnames; this can be used to prune the search, impose a specific order of visiting, or even to inform walk() about directories the caller creates or renames before it resumes walk() again.
请注意,您需要考虑 folders
中存在的分隔符。例如,当 y:\path1
被遍历根是 y:\path
但你不想在那里停止递归。