2010-06-20 7 views
9

Ich habe einen Ordner mit über 100.000 Dateien, alle nummeriert mit dem gleichen Stub, aber ohne führende Nullen, und die Nummern sind nicht immer zusammenhängend (normalerweise sind sie, aber es gibt Lücken) zB:Stapelumbenennung 100K Dateien mit Python

file-21.png, 
file-22.png, 
file-640.png, 
file-641.png, 
file-642.png, 
file-645.png, 
file-2130.png, 
file-2131.png, 
file-3012.png, 

usw.

ich Batch-Prozess möchte diese gepolstert, zusammenhängende Dateien zu erstellen. z:

file-000000.png, 
file-000001.png, 
file-000002.png, 
file-000003.png, 

Wenn ich den Ordner mit for filename in os.listdir('.'): die Dateien analysiere in der Reihenfolge nicht kommen ich sie mag. Verständlicherweise kommen sie bis

file-1, 
file-1x, 
file-1xx, 
file-1xxx, 

usw. dann

file-2, 
file-2x, 
file-2xx, 

usw. Wie kann ich es in der Reihenfolge der numerischen Wert durch bekommen? Ich bin ein kompletter Python-Noob, aber wenn ich mir die Dokumente anschaue, die ich vermute, könnte ich Map verwenden, um eine neue Liste zu erstellen, die nur den numerischen Teil herausfiltert, und dann diese Liste sortieren und dann iterieren? Bei über 100K-Dateien könnte das schwer sein. Irgendwelche Tipps willkommen!

+0

definiert ist, können Sie mit einer beliebigen Anzahl von Parametern ein Linux „ls“ Befehl ausführen, sie zu sortieren, wie Sie wollen ... und dann diese Liste verwenden, um die Dateien zu erhalten. – bwawok

+1

Ja, wenn ich das machen würde, würde ich einfach 'sort -n' verwenden. –

+0

Anstatt Ihre Frage mit der Antwort zu bearbeiten, ist es besser, Ihre Lösung einfach als eigene Antwort am Ende zu posten und als akzeptiert zu markieren. –

Antwort

4

Vielen Dank für Ihre Anregungen, ich werde versuchen, sie alle die verschiedenen Ansätze zu lernen. Die Lösung, für die ich mich entschieden habe, basiert auf der Verwendung einer natürlichen Sortierung in meiner Dateiliste und der anschließenden Iteration zum Umbenennen.Dies war eine der vorgeschlagenen Antworten, aber aus irgendeinem Grund ist es jetzt verschwunden, also kann ich es nicht als akzeptiert markieren!

import os 
files = os.listdir('.') 
natsort(files) 
index = 0 
for filename in files: 
    os.rename(filename, str(index).zfill(7)+'.png') 
    index += 1 

wo natsort in http://code.activestate.com/recipes/285264-natural-string-sorting/

0

1) Nimm die Nummer im Dateinamen. 2) Left-Pad mit Nullen 3) Name speichern.

+0

Dies ignoriert die Lücken in Zahlen. –

1

Warum machen Sie das nicht in einem zweistufigen Prozess? Analysieren Sie alle Dateien und benennen Sie sie mit aufgefüllten Zahlen um, und führen Sie dann ein anderes Skript aus, das die jetzt korrekt sortierten Dateien übernimmt und sie so umbenennt, dass sie zusammenhängend sind.

+0

Der Umbenennungsvorgang, ein Systemaufruf, ist der Engpass: doppelt so viele von denen zu tun, wird doppelt so lange dauern. Sehen Sie meine Antwort für eine schnelle Möglichkeit (mit einer einzigen Umbenennung pro Datei). –

+1

Sie würden sie im Speicher umbenennen, Sie würden sie nicht auf diese Weise auf die Festplatte schreiben. Also nur einen schreiben. –

4

Es gibt drei Schritte. Das erste ist, alle Dateinamen zu bekommen. Die zweite konvertiert die Dateinamen. Die dritte benennt sie um.

Wenn sich alle Dateien im selben Ordner befinden, sollte glob funktionieren.

import glob 
filenames = glob.glob("/path/to/folder/*.txt") 

Als nächstes möchten Sie den Namen der Datei ändern. Sie können dazu mit einem Padding drucken.

>>> filename = "file-338.txt" 
>>> import os 
>>> fnpart = os.path.splitext(filename)[0] 
>>> fnpart 
'file-338' 
>>> _, num = fnpart.split("-") 
>>> num.rjust(5, "0") 
'00338' 
>>> newname = "file-%s.txt" % num.rjust(5, "0") 
>>> newname 
'file-00338.txt' 

Jetzt müssen Sie alle umbenennen. os.rename macht genau das.

os.rename(filename, newname) 

Um es zusammen:

for filename in glob.glob("/path/to/folder/*.txt"): # loop through each file 
    newname = make_new_filename(filename) # create a function that does step 2, above 
    os.rename(filename, newname) 
+0

Dies ignoriert das Problem mit den übersprungenen Nummern in den ursprünglichen Dateinamen - siehe meine Antwort, wie man es leicht beheben kann! –

8
import re 
thenum = re.compile('^file-(\d+)\.png$') 

def bynumber(fn): 
    mo = thenum.match(fn) 
    if mo: return int(mo.group(1)) 

allnames = os.listdir('.') 
allnames.sort(key=bynumber) 

Jetzt können Sie die Dateien in der Reihenfolge, die Sie wollen haben und Schleife kann

for i, fn in enumerate(allnames): 
    ... 

die fortlaufende Nummer i mit (die wird 0, 1, 2, ...) im Ziel-Namen aufgefüllt.

+0

Vielleicht schnellere Sortierfunktion ist Def ByNumber (FN): Return Int (Filter (str.isdigit, Fn)) – twneale

+0

Ja, wenn Sie sicher sind, gibt es keine "streunende" Ziffern überall schneller ist (meine RE-basierte Lösung überprüft auch und der pure Overhead des Schecks, wenn man "weiß", gelingt immer wieder ;-). –

0
def renamer(): 
    for iname in os.listdir('.'): 
     first, second = iname.replace(" ", "").split("-") 
     number, ext = second.split('.') 
     first, number, ext = first.strip(), number.strip(), ext.strip() 
     number = '0'*(6-len(number)) + number # pad the number to be 7 digits long 
     oname = first + "-" + number + '.' + ext 
     os.rename(iname, oname) 
    print "Done" 

this helps

+0

danke, von dem, was ich verstehen kann, wird dies nur die bestehenden Zahlen auffüllen und nicht die Folge zusammenhängend ohne Lücken machen? – memo