os.path.isfile无法按预期工作

时间:2012-01-22 05:25:01

标签: python

我正在尝试扫描我的硬盘以获取jpg和mp3文件。

我编写了以下脚本,如果我在根目录中传递一个带有文件的目录但是如果我将其传递给根目录则不会返回任何内容。

我是Python的新手,所以非常乐意帮忙。

def findfiles(dirname,fileFilter):

    filesBySize = {}

    def filterfiles(f):
        ext = os.path.splitext(f)[1][1:]
        if ext in fileFilter:
            return True
        else:
            False

    for (path, dirs, fnames) in os.walk(dirname):
        if len(fileFilter)>0:
            fnames = filter(filterfiles,fnames)

        d = os.getcwd()
        os.chdir(dirname)      
        for f in fnames:
            if not os.path.isfile(f) :
                continue

            size = os.stat(f)[stat.ST_SIZE]
            if size < 100:
                continue
            if filesBySize.has_key(size):
                a = filesBySize[size]
            else:
                a = []
                filesBySize[size] = a
            a.append(os.path.join(dirname, f))
          #  print 'File Added: %s' %os.path.join(dirname,f)
            _filecount = _filecount + 1
        os.chdir(d)

    return filesBySize

4 个答案:

答案 0 :(得分:10)

啊,是的。

您正在调用os.path.isfile(f),其中fpath中的文件名。您需要提供绝对路径。确实,如果这个调用是必要的(它应该总是返回True)。

尝试将for循环更改为:

    qualified_filenames = (os.path.join(path, filename) for filename in fnames)
    for f in qualified_filenames:

你应该被设定!

此外,不需要拨打os.chdir()

而且,正如我在评论中所建议的,filterfiles看起来应该更像这样:

def filterfiles(f):
    ext = os.path.splitext(f)[1][1:]
    return ext in fileFilter

(你错过了return)。

答案 1 :(得分:3)

filesBySize是非常不寻常的分组。您可以将其移到findfiles()函数之外:

#!/usr/bin/env python
import os
import stat
import sys
from collections import defaultdict

def findfiles(rootdir, extensions=None, minsize=100):
    """Find files with given `extensions` and larger than `minsize`.

    If `extensions` is None then don't filter on extensions.
    Yield size, filepath pairs.
    """
    extensions = tuple(extensions) if extensions is not None else extensions
    for path, dirs, files in os.walk(rootdir):
        if extensions is not None: # get files with given extensions
            files = (f for f in files if f.endswith(extensions))
        for f in files:
            f = os.path.join(path, f) 
            try:
                st = os.stat(f)
            except os.error:
                continue # skip
            if stat.S_ISREG(st.st_mode): # isfile
               if st.st_size > minsize:
                  yield st.st_size, f

rootdir = sys.argv[1] # get it from command-line
files_by_size = defaultdict(list)
for size, f in findfiles(rootdir, ['.mp3', '.jpg']):
    files_by_size[size // (1<<20)].append((size, f)) # group in 1M buckets

import pprint
pprint.pprint(dict(files_by_size)) # pretty print

无需使用os.chdir(),只需拨打os.path.join(path, f)即可。

答案 2 :(得分:2)

与您的问题没有直接关系,但这里有一些一般的现代Python技巧,因为您不熟悉Python:

os.stat(f)[stat.ST_SIZE]

可以写成

os.stat(f).st_size

if filesBySize.has_key(size):
    a = filesBySize[size]
else:
    a = []
    filesBySize[size] = a

最好写成:

a = filesBySize.setdefault(size, [])

答案 3 :(得分:0)

我认为此处不断的os.chdir()调用会使您的程序变得复杂(甚至可能搞砸os.walk()的工作方式。)

我复制了一个更好看的示例,说明如何使用路径名而不更改the Python documentation的目录:

# Delete everything reachable from the directory named in "top",
# assuming there are no symbolic links.
# CAUTION:  This is dangerous!  For example, if top == '/', it
# could delete all your disk files.
import os
for root, dirs, files in os.walk(top, topdown=False):
    for name in files:
        os.remove(os.path.join(root, name))
    for name in dirs:
        os.rmdir(os.path.join(root, name))

您从os.path.join(root, name)选择name后使用files