einsortieren aufgrund des namens

Du hast eine Idee für ein Projekt?
Antworten
zeromancer1608
User
Beiträge: 3
Registriert: Montag 9. Juli 2012, 07:07

Moin liebe community,

ich bin neu in python und ich brauch ein programm mit dem ich alle dateien des selben tages automatisch in einen ordner transferiere und diese dann zippe.

also um das besser zu verdeutlichen, in einem ordner sind dateien mit den namen :

20120510_tag_eins_pic.jpg
20120510_tag_eins_sheet.jpg
20120510_tag_eins_sheet2.jpg
20120511_tag_zwei_pic.jpg
20120511_tag_zwei_sheet.jpg
20120511_tag_zwei_sheet2.jpg

usw.

nun muessen alle dateien des selben tages in einen ordner und das fuer jeden tag eines monats und dann muss der komplette monat gezipt werden.

folgendes habe ich schon, jedoch bekommt jede datei damit einen anderen ordner und ich weiss nich wie ich das am besten so umschreibe das alle eines tages in einem sind.

Code: Alles auswählen

import os, re, shutil

tfolder = 'D:/Testing/src/'

os.chdir(tfolder)

re_year19xxxxxx = re.compile('(19[0-9][0-9][0-9][0-9])')
re_year20xxxxxx = re.compile('(20[0-9][0-9][0-9][0-9])')

re_ed = re.compile('(ED[0-9])')
destPath = 'D:/Testing/Dest/'

def analyse_file_name(fname):
    filePath, coords = os.path.split(fname) #the new folders will be named according to the first 4 characters of the original file name
    coordsFolder = coords[:53]
    coordsFname = coords[:53]
    coordsExt = os.path.splitext(fname)
    year = 'year' #create variable year
    ed = 'ed' #create variable ed to store the edition number if necessary
    bname = fname #the original file name
    for re_year in (re_year19xxxxxx, re_year20xxxxxx):
        rx = re_year.search(fname) #search for regex in the file name and store it in rx
        if rx:
            year = rx.group(1) #if the regex is found, store the year
            bname.replace(year, ' ')
            res = re_ed.search(fname)
            if res:
                ed = res.group(1)
                bname.replace(ed, ' ')
        os.chdir(destPath)
        if year is 'year':
            fname2 = os.path.join(destPath, coordsFolder) + '\\' + coordsFname + coordsExt[1]
        else:
            fname2 = os.path.join(destPath, coordsFolder,year,ed) + '\\' + coordsFname + coordsExt[1]
        print('%s -> %s' % (fname, fname2)) #debug print
        dirn, _ = os.path.split(fname2)
        if not os.path.exists(dirn):
            os.makedirs(dirn)
        shutil.copy(fname, fname2)

for root, dirs, files in os.walk(tfolder):
    for name in files:
        fn = os.path.join(root, name)
        analyse_file_name(fn) 

kann mir da jemand helfen ?

grüße zeromancer
BlackJack

@zeromancer1608: Das ist ziemlich unübersichtlich. Du versuchst da vielleicht zu viel auf einmal zu lösen. Eine Funktion die `analyze_file_name()` heisst sollte einen Dateinamen analysieren und nicht Verzeichnisse anlegen und Dateien kopieren.

`os.chdir()` solltest Du vermeiden. Das macht das Programm schwerer nachvollziehbar, weil man sich zusätzlich immer fragen muss wo zu welchem Zeitpunkt welches Verzeichnis als Arbeitsverzeichnis verwendet wird.

Wieso vermischst Du `os.path.join()` mit dem Zusammensetzen von Pfaden mit ``+`` und einem expliziten Windows-Pfadtrenner?

Die Namensgebung könnte besser sein. Keine Abkürzungen und Namen welche die Bedeutung besser beschreiben wären hilfreich. `fname`, `bname`, und `fname2` sind beispielsweise nicht wirklich verständlich. Zumal `bname` soweit ich das sehe nicht wirklich verwendet wird, das solltest Du rauswerfen. Und das ist ein Zeichen dafür, dass Du so ein bisschen den Überblick verloren hast was Du da eigentlich tust in der Funktion. Warum Du `coordsFolder` und `coordsFname` an den gleichen Wert bindest habe ich auch nicht ganz verstanden. Und `coordsExt` sieht mir auch nicht sinnvoll aus. Da scheinst Du später eine Erweiterung noch einmal *zusätzlich* anzuhängen, sie also zu verdoppeln‽ Natürlich nur sofern das slicen der ersten 53 Zeichen eine eventuelle Dateinamenserweiterung nicht verworfen hat.

``if year is 'year':`` ist ein Fehler. Du möchtest an der Stelle auf Wertegleicheit (``==``) testen und nicht auf Objektidentität (``is``). Wenn das so funktioniert ist das reiner Zufall.

Code: Alles auswählen

In [72]: a = 'spam!'

In [73]: b = 'spam!'

In [74]: a is b
Out[74]: False

In [75]: a == b
Out[75]: True
zeromancer1608
User
Beiträge: 3
Registriert: Montag 9. Juli 2012, 07:07

ja da hast du recht ich habe versucht soviel wie moeglich in einem schritt zu machen und nun hab ich wirklich keine uebersicht mehr.

wie kann ich den mit python den dateinamen auslesen und in einen string speichern und diesen dann mit den anderen vergleichen.
das problem is halt blos das der tag sich aendert, sodass es variable sein muss.
BlackJack

@zeromancer1608: Was meinst Du mit „Dateinamen auslesen”? Wo? Aus dem Dateisystem? Aus einer Zeichenkette die einen Pfad repräsentiert?

Ich würde an Deiner Stelle einfach noch mal bei Null anfangen, das Problem in Teilprobleme zerlegen soweit bis man die Teilprobleme einfach als Quelltext formulieren und dann testen kann. Und erst mit dem nächsten Schritt weiter machen wenn der bis dahin geschriebene Quelltext funktioniert.

Einiges am bisherigen Vorgehen sieht auch ein kleines bisschen „gefährlich” aus. Wenn Du zum Beispiel nur die Dateien in *einem* Verzeichnis verarbeiten möchtest, solltest Du nicht `os.walk()` verwenden. Du suchst die Datums-Muster nicht im Dateinamen sondern im kompletten Pfad — damit fällt das auf die Nase wenn irgendwo im Pfad schon so ein Muster vorkommt. Den Kommentar das der Verzeichnisname Aufgrund der ersten vier Zeichen des Dateinamens erstellt wird, sehe ich im Quelltext nicht umgesetzt. Anlegen und Kopieren wird auf jeden Fall für jeden Dateinamen/Pfad gemacht, auch für solche wo das Muster nicht zutrifft. Ist Dir klar was in diesen Fällen passiert, und soll das so sein?
zeromancer1608
User
Beiträge: 3
Registriert: Montag 9. Juli 2012, 07:07

ich hab jetz nochmal komplett von neuem angefangen und wie du sagst das problem in teilprobleme zerlegt und probier schritt fuer schritt.

ich hab jetz ein defaultdict angelegt und dort splittet er dann und im naechsten schritt legt er einen ordner an und benennt diesen nach den ersten 8 zahlen.
der code sieht so aus:

Code: Alles auswählen

import datetime
import os 
from collections import defaultdict
from shutil import copyfile

dict_date = defaultdict(lambda : defaultdict(list))
for fil in os.listdir(src):
    if os.path.isfile(os.path.join(src, fil)):
        date, animal = fil.split('_')[0:2]
        dict_date[date][animal].append(fil)

for date in dict_date:
        for animal in dict_date[date]:
			try:
				os.makedirs(os.path.join(src, date, animal))
			except os.error:
				pass
			for fil in dict_date[date][animal]:
				copyfile(os.path.join(src, fil), os.path.join(src, date, animal, fil))

nun besteht nur folgendes problem, die dateien die ich sortieren moechten sehen im indeffekt in der art aus " 20120809_1204567_cat_pic1 ; 20120809_1204567_cat_pic2 ; 20120809_1204567_cat_pic3 "
jedoch wird das subfolder jetz nach der 2ten zahl benannt, es soll aber wie hier in dem fall cat heissen.
wie kann ich die zweite zahl ueberspringen damit das subfolder cat heisst ?
BlackJack

@zeromancer1608: In dem Du die Bestandteile aus dem Namen auswählst, die Du haben möchtest. Das hier machst Du:

Code: Alles auswählen

In [76]: filename = '20120809_1204567_cat_pic1'

In [77]: filename.split('_')
Out[77]: ['20120809', '1204567', 'cat', 'pic1']

In [78]: filename.split('_')[0:2]
Out[78]: ['20120809', '1204567']
Das ist offensichtlich nicht das was Du haben möchtest.

Noch mal die Warnung dass hier alle Dateien verarbeitet werden, auch solche die nicht dem Muster entsprechen. Unter Windows muss man zum Beispiel mit einer 'thumbs.db' rechnen die unter Umständen automatisch angelegt wird, wenn man den Ordner mit dem File-Explorer auch nur öffnet um mal zu schauen was für Dateien da drin sind.
Antworten