在目录及其子目录中计算文件夹的数量。

8

我有一个脚本可以精确地告诉我目录中有多少个文件以及其子目录中有多少个文件。但是,我还想知道该目录及其子目录中有多少个文件夹...

我的当前脚本:

import os, getpass
from os.path import join, getsize
user = 'Copy of ' + getpass.getuser()
path = "C://Documents and Settings//" + user + "./"
folder_counter = sum([len(folder) for r, d, folder in os.walk(path)])
file_counter = sum([len(files) for r, d, files in os.walk(path)])
print ' [*] ' + str(file_counter) + ' Files were found and ' + str(folder_counter) + ' folders'

这段代码输出的是:[*] 找到了147个文件和147个文件夹

这意味着folder_counter没有正确地计算元素。如何更正以使folder_counter正确?


你为什么期望将os.walk返回的第三个值重命名会给你不同的结果? - jonrsharpe
因为我是Python的新手,希望它就像那样简单。 - Luke Willmer
但这没有任何意义 - 函数不知道你分配给它返回值的名称(如果有的话!)。 - jonrsharpe
5个回答

27

Python 2.7解决方案

对于单个目录,你也可以这样做:

import os
print len(os.walk('dir_name').next()[1])

这个方法不会加载整个字符串列表,同时返回 'dir_name' 目录中的子目录数量。

Python 3.x 解决方案

由于许多人只想要一个简单快速的解决方案,而不是真正了解解决方案,因此我编辑了我的答案,包括 Python 3.x 的确切工作代码。

所以,在 Python 3.x 中,我们使用 next 方法来替代 .next。因此,上面的代码片段变为:

import os
print(len(next(os.walk('dir_name'))[1]))

其中dir_name是您想要查找其中有多少个目录的目录。


在3.6版本上崩溃并显示错误:AttributeError: 'generator' object has no attribute 'next'。 - Mehdzor
1
当然在Python 3.x中它会崩溃,这不是代码的问题。由于主题与其完全无关,您将需要阅读有关Python 3.x和2.7之间的差异,并阅读并理解您收到的错误信息。 - Xxxo
1
使用[2]可以得到“文件数”,而[1]则表示“文件夹数”。 - agent18

7

我认为你想要类似这样的东西:

import os

files = folders = 0

for _, dirnames, filenames in os.walk(path):
  # ^ this idiom means "we won't be using this value"
    files += len(filenames)
    folders += len(dirnames)

print "{:,} files, {:,} folders".format(files, folders)

请注意,这只会遍历一次os.walk,这将使在包含大量文件和目录的路径上运行更快。在我的Python目录上运行它给了我以下结果:
30,183 files, 2,074 folders

这与Windows文件夹属性视图所显示的完全匹配。


请注意,您当前的代码计算了相同的数字两次,因为唯一的更改是将调用os.walk返回的一个值重命名:
folder_counter = sum([len(folder) for r, d, folder in os.walk(path)])
                        # ^ here          # ^ and here
file_counter = sum([len(files) for r, d, files in os.walk(path)])
                      # ^ vs. here     # ^ and here

尽管更改了名称,您仍在计算相同的值(即在两个值中都使用第三个返回的值)!Python函数不知道它们返回的值将被分配给哪些名称(如果有的话;例如,您可以执行print list(os.walk(path))),并且它们的行为肯定不会因此而改变。根据文档os.walk返回一个三元组(dirpath, dirnames, filenames),您用于该元组的名称,例如是否:
for foo, bar, baz in os.walk(...):

或者:

for all_three in os.walk(..):

不会改变。


1
那正是我正在寻找的,感谢您解释为什么我的简单快速尝试失败了! - Luke Willmer

4

如果只对 /input/dir 中的文件夹数量感兴趣(而不是子目录):

import os

folder_count = 0  # type: int
input_path = "/path/to/your/input/dir"  # type: str
for folders in os.listdir(input_path):  # loop over all files
    if os.path.isdir(os.path.join(input_path, folders):  # if it's a directory
        folder_count += 1  # increment counter

print("There are {} folders".format(folder_count))

您好Tommaso,是否有可能计算给定路径中目录的数量而不包括子目录? - Max Will
嗨,Nikhil!我的答案完全符合你的要求。它只计算目录(而不是子目录)。也许发一个例子,这样我们可以进一步讨论。 - Tommaso Di Noto
以上答案是错误的,os.listdir返回目录和文件。 - APP Bird
1
嗨@APPBird!我修改了答案。现在它只保留目录,但是仅限于当前目录,而不包括子目录。 - Tommaso Di Noto

1
>>> import os
>>> len(list(os.walk('folder_name')))

根据 os.walk 的说明,第一个参数dirpath枚举所有目录。

这将计算目录,并在计数中包括路径(这可能是需要的,也可能不需要)。 - jonrsharpe
不是计算目录是你想要的吗?我测试了代码,它枚举了我指定文件夹内的所有目录。 如果你不需要根路径,你可以减去1。 - Vighnesh Birodkar
  1. 我不是楼主。
  2. 根据问题中的代码,他们想要两者都有。
- jonrsharpe
我不确定你所说的“both”是什么意思。 - Vighnesh Birodkar
抱歉:文件和文件夹/目录都不行。 - jonrsharpe
显示剩余2条评论

0

pathlib 提供了一种方便的方法来实现这个。

path = Path('/path/to/your/directory')
files = dirs = 0
for f in path.iterdir():
    if f.is_dir():
        dirs += 1
    elif f.is_file():
        files += 1

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接