2012-08-23 13 views
20

Diciamo che ho tre file in una cartella: file9.txt, file10.txt e file11.txt e voglio leggerli in questo particolare ordine. Qualcuno mi può aiutare con questo?Lettura di file in un particolare ordine in python

In questo momento sto usando il codice

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

e si legge prima file10.txt poi file11.txt e poi file9.txt.

Qualcuno può aiutarmi a ottenere l'ordine giusto?

risposta

41

I file sul filesystem non sono ordinati. È possibile ordinare i nomi dei file risultanti da soli, usando il sorted() function:

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

Si noti che la chiamata os.path.join nel codice è un no-op; con un solo argomento non fa altro che restituire inalterato quell'argomento.

Si noti che i file verranno ordinati in ordine alfabetico, che inserisce 10 prima del 9. È possibile utilizzare una funzione chiave personalizzata per migliorare l'ordinamento:

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 funzione numericalSort divide eventuali cifre in un nome di file, lo trasforma in un numero reale, e restituisce il risultato per l'ordinamento:

>>> 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. Sfortunatamente, la funzione ordinata non cambia l'ordine. – user1620012

+0

@ user1620012: aggiornata la mia risposta per migliorare l'ordinamento. –

+0

hi..actually i miei file hanno nomi come .. text-text9-text.txt, text-text10-text.txt ecc. – user1620012

6

È possibile avvolgere l'espressione glob.glob(...) all'interno di un'istruzione sorted(...) e ordinare l'elenco di file risultante. Esempio:

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

Si può dare sorted una funzione di confronto o, meglio, utilizzare l'argomento key= ... per dargli una chiave personalizzata che viene utilizzato per l'ordinamento.

Esempio:

Ci sono i seguenti file:

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

Il codice seguente produrrà il seguente output:

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 

Ora con funzione di tasto:

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: Probabilmente questa funzione chiave può ordinare i file:

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. 

sicuramente può essere migliorato, ma penso che si ottiene il punto. I percorsi senza numeri saranno lasciati soli, i percorsi con i numeri verranno convertiti in una stringa di 10 cifre di larghezza e contenente il numero.

+0

La funzione ordinata non modifica l'ordine sfortunatamente. – user1620012

+0

Lo fa - 'y/blub05.txt' si sposta dall'ultima posizione uno perché' blub05.txt' viene prima di 'blub10.txt'. Solo il nome del file viene confrontato senza la directory in 'key_func'. – hochl

+0

In realtà i miei file non hanno gli zeri. Vengono rinominati x/blub1.txt x/blub2.txt x/blub10.txt e questo produce un ordine errato, anche con il comando sort. 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

In realtà ho alcuni file di file che desidero elaborare. Quindi rendere la lista è piuttosto scomodo. La funzione ordinata – user1620012

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

restituisce una lista di stringhe, in modo da poter facilmente ordinare l'elenco utilizzando pitoni sorted() function.

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

restituisce lo stesso risultato Il file corrente elaborato è: file10.txt.txt Il file corrente elaborato è: file11.txt.txt Il file corrente elaborato è: file9.txt.txt – user1620012

0

È necessario modificare l'ordinamento da 'ASCIIBetical' a numerico isolando il numero nel nome file. Si può fare in questo modo:

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 

cui è possibile impostare i nomi dei file con il risultato di glob.glob; ("* .txt").

In aggiunta, la funzione keyFunc presuppone che il nome del file abbia un numero e che il numero sia solo nel nome file. È possibile modificare tale funzione in modo che sia complessa quanto è necessario per isolare il numero da ordinare.

+0

Cosa succede se ci sono file con diversi nomi, raggruppati con numeri? Ex. 'foo1.txt',' foo2.txt' .. 'foo10.txt', quindi' bar1.txt', 'bar2.txt', etc? O ci sono due serie di numeri nel nome del file? –

+0

@MartijnPieters: Non era un requisito della domanda originale e penso che tu conosca la risposta. :) – grieve

+0

Beh, molto probabilmente la domanda utilizzava un piccolo campione di file; come risulta la sequenza '9',' 10', '11' è stata la parte cruciale. Non possiamo presumere di avere l'intera immagine qui. :-) –