2012-01-22 8 views
7

jpgとmp3ファイル用のハードドライブをスキャンしようとしています。os.path.isfileが正常に動作しない

次のスクリプトは、ルートにファイルを含むディレクトリを渡しても、ルートディレクトリに渡しても何も返さない場合に動作します。

私は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 
+1

ディレクトリを再帰的に検索しようとしていますか? – alexmherrmann

+1

この機能には多くのコードがあります。 'os.path.isfile(f)'への呼び出しが間違っているとあなたは確信していますか?また、あなたの関数 'filterfiles()'は、おそらく 'filefilter'を返すべきです。 – Johnsyweb

+0

はい私はあります。私はこれを踏まえたときに、組み込み関数がfが実ファイルであるときにfalseを返すという問題があると思います。私は道を離れることができた。タイプミスがどこにあるか分かりませんか? – gmoorevt

答えて

9

ああはい。

os.path.isfile(f)ここで、fpathのファイル名です。 アブソリュートパスを指定する必要があります。実際にこの呼び出しが必要な場合(常にTrueを返す必要があります)。

は変更してみてください、あなたにループのために:

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

ありがとう!これはトリックでした。助けてくれてありがとう。 – gmoorevt

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)) 

あなたはfilesからnameを選択したらあなたはos.path.join(root, name)を使用しています。

2

直接あなたの質問に関連しますが、ここであなたは、Pythonに新しいしているので、いくつかの一般的な現代のPythonのヒントわけではありません:

os.stat(f)[stat.ST_SIZE] 

​​

if filesBySize.has_key(size): 
    a = filesBySize[size] 
else: 
    a = [] 
    filesBySize[size] = a 
のように記述することができます

は次のように書かれています。

a = filesBySize.setdefault(size, []) 
+1

またはさらに、['filesBySize = defaultdict(list); ... filesBySize [size] .append(f) '](http://stackoverflow.com/a/8959455/4279)' a'なし。 – jfs

3

filesBySizeはかなり珍しいグループです。あなたはfindfiles()関数の外に移動できます。os.chdir()を使用する必要はありません

#!/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.path.join(path, f)を呼び出すのに十分です。

関連する問題