2012-08-23 16 views
20

Digamos que tengo tres archivos en una carpeta: archivo9.txt, archivo10.txt y archivo11.txt y quiero leerlos en este orden particular. Puede alguien ayudarme con esto?Leyendo archivos en un orden particular en python

En este momento estoy usando el código

import glob, os 
for infile in glob.glob(os.path.join('*.txt')): 
    print "Current File Being Processed is: " + infile 

y se lee primero file10.txt continuación file11.txt y luego file9.txt.

¿Alguien me puede ayudar a obtener el pedido correcto?

Respuesta

41

Los archivos en el sistema de archivos no están ordenados. Puede ordenar los nombres de los archivos resultantes por sí mismo utilizando la sorted() function:

for infile in sorted(glob.glob('*.txt')): 
    print "Current File Being Processed is: " + infile 

Tenga en cuenta que la llamada os.path.join en su código es un no-op; con solo un argumento, no hace nada más que devolver ese argumento inalterado.

Tenga en cuenta que sus archivos ordenarán en orden alfabético, lo que pone 10 antes de 9. Puede utilizar una función clave personalizada para mejorar la clasificación:

import re 
numbers = re.compile(r'(\d+)') 
def numericalSort(value): 
    parts = numbers.split(value) 
    parts[1::2] = map(int, parts[1::2]) 
    return parts 

for infile in sorted(glob.glob('*.txt'), key=numericalSort): 
    print "Current File Being Processed is: " + infile 

La función numericalSort divide a cabo ningún dígito en un nombre de archivo, lo convierte en un número real, y devuelve el resultado de la clasificación:

>>> files = ['file9.txt', 'file10.txt', 'file11.txt', '32foo9.txt', '32foo10.txt'] 
>>> sorted(files) 
['32foo10.txt', '32foo9.txt', 'file10.txt', 'file11.txt', 'file9.txt'] 
>>> sorted(files, key=numericalSort) 
['32foo9.txt', '32foo10.txt', 'file9.txt', 'file10.txt', 'file11.txt'] 
+0

HI. La función ordenada no cambia el orden desafortunadamente. – user1620012

+0

@ user1620012: actualicé mi respuesta para mejorar el orden de clasificación. –

+0

hola ... en realidad, mis archivos tienen los siguientes nombres: texto-texto9-texto.txt, texto-texto10-texto.txt etc. – user1620012

6

Puede envolver su expresión glob.glob(...) dentro de una declaración sorted(...) y ordenar la lista resultante de archivos. Ejemplo:

for infile in sorted(glob.glob('*.txt')): 

Usted puede dar sorted una función de comparación, o mejor, utilice el argumento key= ... para darle una clave personalizada que se utiliza para la clasificación.

Ejemplo:

Existen los siguientes archivos:

x/blub01.txt 
x/blub02.txt 
x/blub10.txt 
x/blub03.txt 
y/blub05.txt 

El siguiente código producirá el siguiente resultado:

for filename in sorted(glob.glob('[xy]/*.txt')): 
     print filename 
# x/blub01.txt 
# x/blub02.txt 
# x/blub03.txt 
# x/blub10.txt 
# y/blub05.txt 

Ahora con función clave:

def key_func(x): 
     return os.path.split(x)[-1] 
for filename in sorted(glob.glob('[xy]/*.txt'), key=key_func): 
     print filename 
# x/blub01.txt 
# x/blub02.txt 
# x/blub03.txt 
# y/blub05.txt 
# x/blub10.txt 

EDIT: Posiblemente esta función clave puede ordenar sus archivos:

pat=re.compile("(\d+)\D*$") 
... 
def key_func(x): 
     mat=pat.search(os.path.split(x)[-1]) # match last group of digits 
     if mat is None: 
      return x 
     return "{:>10}".format(mat.group(1)) # right align to 10 digits. 

Seguro que se puede mejorar, pero creo que usted consigue el punto. Se dejarán las rutas sin números, las rutas con números se convertirán en una cadena de 10 dígitos de ancho y contiene el número.

+0

Desafortunadamente, la función ordenada no cambia el orden. – user1620012

+0

Lo hace - 'y/blub05.txt' se mueve de la última posición uno arriba porque' blub05.txt' viene antes de 'blub10.txt'. Solo el nombre del archivo se compara sin el directorio en 'key_func'. – hochl

+0

En realidad, mis archivos no tienen los ceros. Se renombraron como x/blub1.txt x/blub2.txt x/blub10.txt y esto produce un orden incorrecto, incluso con el comando de ordenación. x/blub3.txt y/blub5.txt – user1620012

-1
for fname in ['file9.txt','file10.txt','file11.txt']: 
    with open(fname) as f: # default open mode is for reading 
     for line in f: 
     # do something with line 
+0

En realidad, tengo algunos cientos de archivos que quiero procesar. Por lo tanto, hacer la lista es bastante incómodo. – user1620012

0
glob.glob(os.path.join('*.txt')) 

devuelve una lista de cadenas, por lo que se puede ordenar fácilmente la lista mediante pitones sorted() function.

sorted(glob.glob(os.path.join('*.txt'))) 
+0

función ordenada da el mismo resultado El archivo actual que se está procesando es: archivo10.txt.txt El archivo actual se está procesando es: archivo11.txt.txt El archivo actual se está procesando es: archivo9.txt.txt – user1620012

0

Debe cambiar el tipo de 'ASCIIBetical' a numérico mediante el aislamiento del número en el nombre del archivo. Puede hacerlo de esta manera:

import re 

def keyFunc(afilename): 
    nondigits = re.compile("\D") 
    return int(nondigits.sub("", afilename)) 

filenames = ["file10.txt", "file11.txt", "file9.txt"] 

for x in sorted(filenames, key=keyFunc): 
    print xcode here 

donde se puede establecer nombres de archivo con el resultado de glob.glob; ("* .txt").

Additinally la función keyFunc supone que el nombre de archivo tendrá un número y que el número solo está en el nombre del archivo. Puede cambiar esa función para que sea lo más compleja que necesite para aislar el número que necesita ordenar.

+0

¿Qué pasa si hay archivos con diferente nombres, agrupados con números? Ex. 'foo1.txt',' foo2.txt' .. 'foo10.txt', luego' bar1.txt', 'bar2.txt', etc.? ¿O hay dos conjuntos de números en el nombre del archivo? –

+0

@MartijnPieters: No era un requisito de la pregunta original, y creo que ya conoce la respuesta. :) – grieve

+0

Bueno, lo más probable es que la pregunta usara una pequeña muestra de archivos; como resultado, la secuencia '9',' 10', '11' fue la parte crucial. No podemos suponer que tenemos toda la imagen aquí. :-) –

Cuestiones relacionadas