递归目录列表/分析函数似乎不正确递归

0 投票
2 回答
953 浏览
提问于 2025-04-16 05:34

我写了一个我认为很简单的Python脚本,用来遍历一个指定的文件夹,并列出它找到的所有文件后缀。输出结果是这样的:

OTUS-ASIO:face fish$ sufs

>>>         /Users/fish/Dropbox/ost2/face (total 194)
===                    1       1      -
===                  css      16      -----
===                  gif      14      -----
===                 html      12      ----
===                  icc      87      --------------------------
===                  jpg       3      -
===                   js      46      --------------
===                  png       3      -
===                  zip       2      -

... 如果这些值是正确的,那就太好了。但实际上并不是。下面是我在上面提到的目录的一个子目录中运行这个脚本时发生的事情:

OTUS-ASIO:face fish$ cd images/
OTUS-ASIO:images fish$ sufs

>>>         /Users/fish/Dropbox/ost2/face/images (total 1016)
===                  JPG       3      -
===                  gif      17      -
===                  ico       1      -
===                 jpeg       1      -
===                  jpg     901      --------------------------
===                  png      87      ---

... 它似乎只向下遍历了一层目录。当我在上面一层运行这个脚本时,完全没有找到'jpeg'这个后缀,而且似乎漏掉了大约898个jpg文件。

这个脚本的内容在这里:

#!/usr/bin/env python
# encoding: utf-8
"""
getfilesuffixes.py

Created by FI$H 2000 on 2010-10-15.
Copyright (c) 2010 OST, LLC. All rights reserved.
"""

import sys, os, getopt

help_message = '''
Prints a list of all the file suffixes found in each DIR, with counts.
Defaults to the current directory wth no args.

$ %s DIR [DIR DIR etc ...]
''' % os.path.basename(__file__)

dirs = dict()
skips = ('DS_Store','hgignore')

class Usage(Exception):
    def __init__(self, msg):
        self.msg = msg

def getmesomesuffixes(rootdir, thisdir=None):
    if not thisdir:
        thisdir = rootdir

    for thing in [os.path.abspath(h) for h in os.listdir(thisdir)]:
        if os.path.isdir(thing):
            getmesomesuffixes(rootdir), thing)
        else:
            if thing.rfind('.') > -1:
                suf = thing.rsplit('.').pop()
                dirs[rootdir][suf] = dirs[rootdir].get(suf, 0) + 1
    return

def main(argv=None):
    if argv is None:
        argv = sys.argv
    try:
        try:
            opts, args = getopt.getopt(argv[1:], "h", ["help",])
        except getopt.error, msg:
            raise Usage(msg)
        for option, value in opts:
            if option == "-v":
                verbose = True
            if option in ("-h", "--help"):
                raise Usage(help_message)

        if len(args) == 0:
            args.append(os.getcwd())

        for durr in [os.path.abspath(arg) for arg in args]:
            if os.path.isdir(durr):
                dirs[durr] = dict()

        for k, v in dirs.items():
            getmesomesuffixes(k)

        print ""

        for k, v in dirs.items():
            sufs = v.items()
            sufs.sort()

            maxcount = reduce(lambda fs, ns: fs > ns and fs or ns, map(lambda t: t[1], sufs), 1)
            mincount = reduce(lambda fs, ns: fs < ns and fs or ns, map(lambda t: t[1], sufs), 1)
            total = reduce(lambda fs, ns: fs + ns, map(lambda t: t[1], sufs), 0)
            print ">>>\t\t\t%s (total %s)" % (k, total)

            for suf, sufcount in sufs:
                try:
                    skips.index(suf)
                except ValueError:
                    print "===\t\t\t%12s\t %3s\t  %s" % (suf, sufcount, "-" * (int(float(float(sufcount) / float(maxcount)) * 25) + 1))
            print ""


    except Usage, err:
        print >> sys.stderr, sys.argv[0].split("/")[-1] + ": " + str(err.msg)
        print >> sys.stderr, "\t for help use --help"
        return 2


if __name__ == "__main__":
    sys.exit(main())

看起来getmesomesuffixes()这个函数似乎没有按我想要的方式工作。我不想问这样一个让人烦恼的问题,但如果有人能快速看一眼,找出我这个新手犯的错误,那将省去我不少麻烦。

2 个回答

1

在编程中,有时候我们会遇到一些问题,特别是在使用某些工具或库的时候。比如说,有人可能在使用一个叫做“库”的东西时,发现它的某些功能不太好用,或者不太符合自己的需求。这种时候,我们就需要去寻找解决办法,或者看看有没有其他人遇到过类似的问题。

通常,大家会在一个叫做StackOverflow的网站上提问和回答问题。这个网站就像一个大社区,里面有很多程序员分享他们的经验和解决方案。如果你在编程过程中遇到困难,可以在这里搜索一下,看看有没有人已经解决了类似的问题。

有时候,问题的解决方案可能会涉及到一些代码示例,这些代码示例可以帮助你更好地理解如何解决问题。记得在查看这些示例时,仔细阅读每一行代码,理解它们的作用,这样才能更好地应用到自己的项目中。

总之,遇到问题时不要慌张,先去查找资料,看看别人是怎么解决的,慢慢你就会积累更多的经验,变得越来越厉害!

import os
import os.path
from collections import defaultdict

def foo(dir='.'):
    d = defaultdict(int)   
    for _, _, files in os.walk(dir):
        for f in files:
            d[os.path.splitext(f)[1]] += 1
    return d

if __name__ == '__main__':
    d = foo()
    for k, v in sorted(d.items()):
        print k, v
3

是啊,如果你用 os.walk 可能会更好。

for root, dirs, files in os.walk(basedir):
    ... do you stuff ..

可以看看这个例子:

另外,看看 os.path.splitext(path),这是一个更好的方法来找出你文件的类型。

>>> os.path.splitext('/d/c/as.jpeg')
('/d/c/as', '.jpeg')
>>> 

把这两者结合起来,应该能让你的代码更简单。

撰写回答