Fotos sortieren (Python?)

njchw

Lt. Commander
Registriert
März 2015
Beiträge
1.178
Servus!
Ich habe eine Idee für ein Programm, dass einen Haufen an unsortierten Fotos sortieren soll. In welcher Programmiersprache ich es schreiben soll weiß ich noch nicht, vlt Python, das ist die einzige Sprache die ich halbwegs kann. Hier kommt meine Idee, bzw. mein Konzept. Bitte schreibt mir keinen kompletten Quelltext, sondern gebt mir lieber Tips wie und in welcher Sprache ich es umsetzen soll.

FOTOS SORTIEREN (voraussichtlich in Python)

--> FUNKTIONEN
1.: scannt vorgegebenen Ordner (z.B. /home/user/Bilder)
2.: verschiebt alle "nicht-Bilder", alle Dateien die nicht eine Grafikdateiendung haben in anderen Ordner (z.B. /home/user/Dokumente)
3.: ließt die Metadaten von den Bildern aus und sortiert sie so:
/home/user/Bilder/2015/10/02 oder /home/user/Bilder/2015/10.
Ich habe mir das rein von der Logik so vorgestellt:
Das Programm ließt die Metas von allen Bildern aus. Wenn es Bilder von 2013 und 2015 gibt erstellt es die Ordner 2013 und 1015 - usw. und verschiebt dann alle Bilder in den entsprechenden Ordner. Wenn Bilder schon in einem Unterordner waren (/home/user/Bilder/asdfasdfasdf) wird nach Abschluss des Vorgangs der Ordner asdfasdfasdf gelöscht.

Wie kann ich dieses Programm am Besten umsetzen?
LG njchw
 
Klingt nach ner netten Aufgabe fürs Wochenende. Ich würde an Deiner Stelle aber keine Dateien verschieben, sondern lieber kopieren. Dann kannst Du falls was schiefläuft, Deine Originaldateien nicht zerstören. Wenn Du dem Prozess vertraust, kannst Du dann immer noch am Ende eine Löschfunktion nach dem Kopieren einbauen.
 
njchw schrieb:
2.: verschiebt alle "nicht-Bilder", alle Dateien die nicht eine Grafikdateiendung haben in anderen Ordner (z.B. /home/user/Dokumente)

Ich würde die Bilder in einen (optional vom Benutzer benannten) Ordner kopieren (und das Löschen optional machen). Vorteil: So kann man Bilder auch bei mehreren Scanvorgängen an einem Ort zusammenführen. Ich würde immer kopieren und wenn löschen gewünscht, erst nach Überprüfung, dass korrekt kopiert wurde, löschen. Du willst keine Bilder beim Verschieben beschädigen oder verlieren.


njchw schrieb:
Wie kann ich dieses Programm am Besten umsetzen?

Soll das ein Kommandozeilen-Programm werden oder ist (auch) eine GUI geplant?

Du überlegst Dir, was das Programm alles machen soll (Du hast die einzelnen Schritte ja schon grob benannt) und setzt das dann sukzessive um.

Der Einfachheit halber kann man am Anfang mögliche Optionen hardkodieren. Ich würde mit der Scan-Funktion anfangen (hier verwendet man üblicherweise os.walk(), Du willst vermutlich auch Unterordner durchsuchen?).
 
Ich möchte dass das Programm ganz einfach im Terminal läuft. @HominiLupus: exifread ist für Python 2. Ich würde das Programm gerne mit Python 3 machen, oder ist es egal wenn ich es mit der alten Version mache?
 
Mit PIL kommst du auch an die EXIF-Daten ran, für Python3 einfach Pillow verwenden.
Statt selbst rekursiv listdir aufzurufen kannst du os.walk verwenden. (gerade gesehen dass das schon gesagt wurde)

Falls du mehr als nur ein-/ausgabepfad an optionen hast kannst du getopt oder argparse verwenden um Kommandozeilenargumente zu verarbeiten. Oder du verwendest einfach eine config.py, je nach dem was dir für deinen Verwendungszweck am besten passt.

Beispiel:

Code:
# config.py
input_directory = '/home/user/Bilder'
output_directory = '/home/user/output'
image_extensions = ['jpg', 'jpeg', 'png', 'bmp']

Code:
# process_images.py

import config

def process_images(input_dir, output_dir):
    # code hier
    # for files in dir: if extension(file) in config.image_extensions ...
    raise NotImplementedError()


if __name__ == '__main__':
    process_images(config.input_directory, config.output_directory)
 
Zuletzt bearbeitet:
Backslash schrieb:
Falls du mehr als nur ein-/ausgabepfad an optionen hast kannst du getopt oder argparse verwenden um Kommandozeilenargumente zu verarbeiten.

Ich würde argparse nehmen. Sehr einfach zu verwenden und Du hast auch gleich ein "Benutzerinterface".
 
libmagic

Backslash schrieb:
Code:
image_extensions = ['jpg', 'jpeg', 'png', 'bmp']
Für die Dateityp-Bestimmung die Endung heranzuziehen mag in vielen Fällen ausreichend sein. Ansonsten kann man auch auf die Bibliothek libmagic zurückgreifen, die ja auch das Systemkommando file benutzt.

Für Python existieren (natürlich) auch dazu schon Bindungen wie python3-magic.

Siehe dazu auch: https://github.com/ahupp/python-magic


Beispiel:
Code:
import magic

def get_file_type(filename):
    m = magic.open(magic.MAGIC_MIME)
    m.load()
    return(m.file(filename))

print(get_file_type("dateiname.jpg"))

Die Bibliothek selbst sollte im Repository jeder gut sortierten Linux-Distribution zu finden sein.

Gruß
Andy
 
Backslash schrieb:
Mit PIL kommst du auch an die EXIF-Daten ran, für Python3 einfach Pillow verwenden.
Statt selbst rekursiv listdir aufzurufen kannst du os.walk verwenden. (gerade gesehen dass das schon gesagt wurde)

Falls du mehr als nur ein-/ausgabepfad an optionen hast kannst du getopt oder argparse verwenden um Kommandozeilenargumente zu verarbeiten. Oder du verwendest einfach eine config.py, je nach dem was dir für deinen Verwendungszweck am besten passt.

Beispiel:

Code:
# config.py
input_directory = '/home/user/Bilder'
output_directory = '/home/user/output'
image_extensions = ['jpg', 'jpeg', 'png', 'bmp']

Ich würde es lieber so machen:


Code:
input_directory = input("Gib bitte die Quelldatei an: ")
output_directory = input("Und die Zieldatei: ")

#und dann einfach als image_extensions alle gängigen Grafikformate + RAW
 
njchw schrieb:
Ich würde es lieber so machen:

Code:
input_directory = input("Gib bitte die Quelldatei an: ")
output_directory = input("Und die Zieldatei: ")

Nimmt argparse! Dann kannst Du wie gewünscht Parameter angeben, das Programm fragt aber nicht ständig nach und lässt sich deswegen auch automatisiert aufrufen. Damit bleibst Du flexibel. Wenn benötigte Parameter nicht angegeben sind, bekommt man eine Fehlermeldung.

Code:
usage: size.py [-h] [-s integer] [-d integer] directory [directory ...]
size.py: error: too few arguments

Dann ruft man size -h auf und bekommt die Hilfe angezeigt:

Code:
usage: size.py [-h] [-s integer] [-d integer] directory [directory ...]

Searches given directories and lists files found.

positional arguments:
  directory             the directories to search

optional arguments:
  -h, --help            show this help message and exit
  -s integer, --size integer
                        only list files bigger than threshold (default: 1 MB)
  -d integer, --depth integer
                        recurse given number of levels (default: all)

Das alles erreicht man mit sieben Zeilen Code:

Code:
def parse_args():
  parser = argparse.ArgumentParser(description='Searches given directories and lists files found.')
  parser.add_argument('directories', metavar='directory', help='the directories to search', nargs='+')
  parser.add_argument('-s', '--size', metavar='integer', dest='size', type=int, default=1048576, help='only list files bigger than threshold (default: 1 MB)')
  parser.add_argument('-d', '--depth', metavar='integer', dest='depth', type=int, default=-1, help='recurse given number of levels (default: all)')
  return parser.parse_args()

def main():
  args = parse_args()
  ...

if __name__ == "__main__":
    main()


Ich würde für das Zielverzeichnis einen sinnvollen Default verwenden, der per Parameter überschrieben werden kann. Die Quellverzeichnisse (warum sich auf ein Verzeichnis beschränken?) müssen wie in meinem Beispiel immer angegeben werden.
 
Wenn du viel mit Exif-Daten arbeiten willst, würde ich Perl empfehlen. Das wichtigste Exiftool ist in Perl geschrieben.
 
Es gibt einen Wrapper dafür, falls die Python-Libs nicht ausreichend sein sollten: http://smarnach.github.io/pyexiftool/. Ich würde nicht wegen diesem Tool auf Perl setzen.

Die Verarbeitung der Dateien könnte man parallelisieren, um die Performance zu steigern. Python ab 3.2 bietet da eine ganz nette API.
 
Zurück
Oben