2012-01-22 34 views
7

Estoy intentando escanear mi disco duro para archivos jpg y mp3.os.path.isfile no funciona como se esperaba

He escrito la siguiente secuencia de comandos que funciona si paso un directorio con el archivo en la raíz pero no devuelve nada si lo paso por el directorio raíz.

Soy nuevo en Python, por lo que me gustaría algo de ayuda.

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

¿Está tratando de buscar recursivamente por los directorios? – alexmherrmann

+1

Hay un montón de código en esta función. ¿Qué te hace estar tan seguro de que es la llamada a 'os.path.isfile (f)' que va mal? También su función 'filterfiles()' probablemente debería 'devolver ext en fileFilter', ya que tiene un error tipográfico allí. – Johnsyweb

+0

Sí, lo soy. Supongo que este es el problema, ya que cuando lo paso, la función incorporada devuelve falso cuando f es un archivo real. Podría estar lejos. ¿No estás seguro de dónde ves el error tipográfico? – gmoorevt

Respuesta

9

Ah sí.

Llamas os.path.isfile(f) donde f es el nombre de archivo dentro de path. Tendrá que proporcionar una ruta absoluta. Si, de hecho, esta llamada es necesaria (siempre debe devolver True).

trate de cambiar su ciclo for a:

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

y que debe estar listo!

Además, las llamadas a os.chdir() no son necesarias.

Y, como ya he sugerido en los comentarios, filterfiles debe mirar más a esto:

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

(se ha perdido un return).

+1

Gracias! Esto hizo el truco. Gracias por la ayuda. – gmoorevt

0

Creo que las constantes llamadas os.chdir() aquí están complicando su programa (e incluso podría arruinar cómo os.walk() obras).

He copiado el ejemplo de mejor aspecto de cómo trabajar con los nombres de ruta sin los cambios de directorio de 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)) 

Se utilizan os.path.join(root, name) una vez que haya seleccionado un name de files.

2

no directamente relacionados con su pregunta, pero aquí hay algunos consejos generales Python modernas ya que es nuevo en Python:

os.stat(f)[stat.ST_SIZE] 

se puede escribir como

os.stat(f).st_size 

y

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

está mejor escrito como:

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

o incluso, ['filesBySize = defaultdict (list); ... filesBySize [size] .append (f) '] (http://stackoverflow.com/a/8959455/4279) sin' a'. – jfs

3

filesBySize es una agrupación bastante inusual. Se podía mover fuera findfiles() función:

#!/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 

No hay necesidad de utilizar os.chdir(), es suficiente para llamar os.path.join(path, f).

Cuestiones relacionadas