{"id":333,"date":"2025-04-14T21:26:57","date_gmt":"2025-04-14T19:26:57","guid":{"rendered":"https:\/\/www.davidestecco.it\/it\/?p=333"},"modified":"2026-01-09T14:31:27","modified_gmt":"2026-01-09T13:31:27","slug":"organizzare-le-foto-in-automatico-con-python-come-ho-creato-il-mio-photo-organizer","status":"publish","type":"post","link":"https:\/\/www.davidestecco.it\/it\/2025\/04\/14\/organizzare-le-foto-in-automatico-con-python-come-ho-creato-il-mio-photo-organizer\/","title":{"rendered":"Organizzare le foto in automatico con Python: come ho creato il mio Photo Organizer"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\">Se sei come me, ogni volta che torni da un viaggio o da un evento speciale ti ritrovi con <strong>decine (o centinaia!) di foto<\/strong> sparse ovunque: sulla SD della fotocamera, sul telefono, magari anche sul cloud&#8230; E poi rimandiamo sempre il momento di organizzarle, finendo in un caos totale.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Ecco perch\u00e9 ho deciso di creare un piccolo <strong>programma Python<\/strong> che potesse fare tutto il lavoro sporco per me. Oggi ti presento il mio <strong>Photo Organizer<\/strong>, uno script che ordina automaticamente immagini, video e file RAW, dividendo tutto per anno e mese<\/p>\n\n\n\n<h1 class=\"wp-block-heading\"><strong>Come funziona?<\/strong><\/h1>\n\n\n\n<p class=\"wp-block-paragraph\">Il funzionamento \u00e8 semplice:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Gli dici dove si trovano i tuoi file (ad esempio la scheda SD della fotocamera).<\/li>\n\n\n\n<li>Gli dici dove vuoi che vengano salvati (un hard disk, una cartella sul PC\u2026).<\/li>\n\n\n\n<li>Il programma analizza ogni file e lo sposta nella cartella giusta, basandosi sulla <strong>data di creazione<\/strong>.<\/li>\n<\/ol>\n\n\n\n<p class=\"wp-block-paragraph\">Ad esempio, una foto scattata il 10 agosto 2023 finir\u00e0 in:<\/p>\n\n\n\n<pre class=\"wp-block-verse\">\/Tuodisco\/JPG\/2023\/10-Agosto\/nomedelfile.jpg<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Lo script riconosce automaticamente:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Foto classiche<\/strong> (.jpg, .png, ecc.)<\/li>\n\n\n\n<li><strong>Video<\/strong> (.mp4, .mov, ecc.)<\/li>\n\n\n\n<li><strong>Immagini RAW<\/strong> da fotocamere professionali (.nef, .cr2&#8230;)<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">E se un file \u00e8 gi\u00e0 presente, non lo ricopia. Tutto \u00e8 documentato in un file di log!<\/p>\n\n\n\n<h1 class=\"wp-block-heading\"><strong>Un\u2019occhiata al codice (semplificata!)<\/strong><\/h1>\n\n\n\n<p class=\"wp-block-paragraph\">Ecco un pezzetto chiave del codice che decide dove mettere ogni file:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: python; title: ; notranslate\" title=\"\">\ndef get_dest_path(cfile, HD, file):\n   datafile = \ndatetime.datetime.fromtimestamp(os.path.getmtime(cfile))\n   Anno = HD + datafile.strftime(&quot;%Y&quot;)\n   GiornoMese = Anno + &quot;\/&quot; + datafile.strftime(&quot;%d&quot;) + &quot;-&quot; + \n   mesi&#x5B;int(datafile.strftime(&quot;%m&quot;))-1]\n   return os.path.join(GiornoMese, file)\n<\/pre><\/div>\n\n\n<p class=\"wp-block-paragraph\">In pratica, prende la <strong>data di modifica<\/strong> del file, la trasforma in anno\/mese\/giorno, e costruisce il percorso finale dove copiare il file.<\/p>\n\n\n\n<h1 class=\"wp-block-heading\"><strong>Perch\u00e9 ho usato Python?<\/strong><\/h1>\n\n\n\n<p class=\"wp-block-paragraph\">Python \u00e8 uno dei linguaggi pi\u00f9 semplici e versatili: perfetto per chi vuole <strong>automatizzare attivit\u00e0 ripetitive<\/strong> senza impazzire. Inoltre, grazie a librerie come <code>os<\/code>, <code>shutil<\/code> e <code>tqdm<\/code>, possiamo:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Cercare file dentro cartelle e sottocartelle<\/li>\n\n\n\n<li>Copiarli in modo sicuro<\/li>\n\n\n\n<li>Visualizzare il progresso dell\u2019operazione<\/li>\n<\/ul>\n\n\n\n<h1 class=\"wp-block-heading\"><strong>Come usarlo?<\/strong><\/h1>\n\n\n\n<pre class=\"wp-block-preformatted\">python Photo-Organizer.py \/percorso\/della\/SD \/percorso\/dell\/harddisk\/<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">E voil\u00e0, il tuo archivio fotografico \u00e8 pronto!<\/p>\n\n\n\n<h1 class=\"wp-block-heading\"><strong>Vuoi provarlo anche tu?<\/strong><\/h1>\n\n\n\n<p class=\"wp-block-paragraph\">Questo tipo di script \u00e8 perfetto per chi vuole iniziare con l\u2019automazione in Python. Se vuoi provare anche tu, <strong>scrivimi<\/strong> e sar\u00f2 felice di condividere lo script o aiutarti a personalizzarlo!<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: python; title: ; notranslate\" title=\"\">\nimport os\nimport datetime\nimport shutil\nimport sys\nimport logging\nfrom tqdm import tqdm\n\n# Configura il logging\nlogging.basicConfig(\n    filename=&#039;photo_organizer.log&#039;,  # Nome del file di log\n    level=logging.INFO,  # Impostiamo il livello di log (INFO, DEBUG, ERROR, etc.)\n    format=&#039;%(asctime)s - %(levelname)s - %(message)s&#039;,  # Formato del log\n)\n\nmesi = &#x5B;&quot;Gennaio&quot;, &quot;Febbraio&quot;, &quot;Marzo&quot;, &quot;Aprile&quot;, &quot;Maggio&quot;, &quot;Giugno&quot;, &quot;Luglio&quot;, &quot;Agosto&quot;, &quot;Settembre&quot;, &quot;Ottobre&quot;, &quot;Novembre&quot;, &quot;Dicembre&quot;]\n\nimg = (&quot;.jpg&quot;, &quot;.jpeg&quot;, &quot;.jfif&quot;, &quot;.pjpeg&quot;, &quot;.pjp&quot;, &quot;.png&quot;, &quot;.gif&quot;, &quot;.webp&quot;, &quot;.svg&quot;, &quot;.apng&quot;, &quot;.avif&quot;)\n\nvideo = (&quot;.webm&quot;, &quot;.mts&quot;, &quot;.m2ts&quot;, &quot;.TS&quot;, &quot;.mov&quot;, &quot;.mp4&quot;, &quot;.m4p&quot;, &quot;.m4v&quot;, &quot;.mxf&quot;)\n\nimgraw = (&quot;.nef&quot;, &quot;.cr2&quot;, &quot;.cr3&quot;)\n\ndef main():\n    if len(sys.argv) &lt; 3:\n        print_help()\n        sys.exit(1)\n\n    SD = sys.argv&#x5B;1]\n    HardDisk = sys.argv&#x5B;2]    \n    logging.info(f&quot;Percorso SD: {SD}&quot;)\n    logging.info(f&quot;Percorso HD: {HardDisk}&quot;)\n\n    JPG = HardDisk + &quot;JPG\/&quot;\n    RAW = HardDisk + &quot;RAW\/&quot;\n    VIDEO = HardDisk + &quot;VIDEO\/&quot;\n\n    NumJPGCopiati = 0\n    NumJPGNonCopiati = 0\n    NumRAWCopiati = 0\n    NumRAWNonCopiati = 0\n    NumVIDEOCopiati = 0\n    NumVIDEONonCopiati = 0\n    NumFileEstSbagliata = 0\n    NumFileNonCopiati = 0\n    file_list = &#x5B;]\n    \n    for root, dirs, files in os.walk(SD):\n        for file in files:\n            file_list.append((root, file))\n\n    for root, file in tqdm(file_list, desc=&quot;Copia file&quot;, unit=&quot;file&quot;):\n        if is_image(file):\n            if copia_file(JPG, root, file):\n                NumJPGCopiati += 1\n            else:\n                NumJPGNonCopiati += 1\n        elif is_raw(file):\n            if copia_file(RAW, root, file):\n                NumRAWCopiati += 1\n            else:\n                NumRAWNonCopiati += 1\n        elif is_video(file):\n            if copia_file(VIDEO, root, file):\n                NumVIDEOCopiati += 1\n            else:\n                NumVIDEONonCopiati += 1\n        else:\n            logging.warning(f&quot;{file} - Estensione Sbagliata&quot;)\n            NumFileEstSbagliata += 1\n\n    logging.info(f&quot;Numero JPG COPIATI = {NumJPGCopiati}&quot;)\n    logging.info(f&quot;Numero JPG Non COPIATI = {NumJPGNonCopiati}&quot;)\n    logging.info(f&quot;Numero RAW COPIATI = {NumRAWCopiati}&quot;)\n    logging.info(f&quot;Numero RAW Non COPIATI = {NumRAWNonCopiati}&quot;)\n    logging.info(f&quot;Numero VIDEO COPIATI = {NumVIDEOCopiati}&quot;)\n    logging.info(f&quot;Numero VIDEO Non COPIATI = {NumVIDEONonCopiati}&quot;)\n    logging.info(f&quot;Numero Estensione Sbagliata = {NumFileEstSbagliata}&quot;)\n    \n    TotaleCopiati = NumJPGCopiati + NumRAWCopiati + NumVIDEOCopiati\n    TotaleNonCopiati = NumJPGNonCopiati + NumRAWNonCopiati + NumVIDEONonCopiati + NumFileEstSbagliata\n    \n    logging.info(f&quot;Numero FILE Copiati Totali = {TotaleCopiati}&quot;)\n    logging.info(f&quot;Numero FILE Non Copiati Totali = {TotaleNonCopiati}&quot;)\n    logging.info(f&quot;Numero FILE Totali = {TotaleCopiati + TotaleNonCopiati}&quot;)\n\ndef print_help():\n    print(&quot;Utilizzo:&quot;)\n    print(&quot;  python Photo-Organizer.py &lt;PERCORSO_SORGENTE&gt; &lt;PERCORSO_DESTINAZIONE&gt; ...&quot;)\n    print(&quot;Esempio:&quot;)\n    print(&quot;  python Photo-Organizer.py \/media\/davide\/NIKON D500\/DCIM\/115ND500\/ \/home\/davide\/Immagini\/&quot;)\n    print(&quot;\\nDescrizione:&quot;)\n    print(&quot;  Questo script accetta due argomenti e copia &quot;)\n    print(&quot;  immagini (.jpg, .jpeg, .jfif, .pjpeg, .pjp, .png, .gif, .webp, .svg, .apng, .avif)&quot;)\n    print(&quot;  video (.webm, .mts, .m2ts, .TS, .mov, .mp4, .m4p, .m4v, .mxf)&quot;)\n    print(&quot;  immagini RAW (.nef,.cr2,.cr3)&quot;)\n    print(&quot;  Se non inserisci argomenti, mostra questo messaggio di aiuto.&quot;)\n\ndef get_dest_path(cfile, HD, file):\n    datafile = datetime.datetime.fromtimestamp(os.path.getmtime(cfile))\n    Anno = HD + datafile.strftime(&quot;%Y&quot;)\n    GiornoMese = Anno + &quot;\/&quot; + datafile.strftime(&quot;%d&quot;) + &quot;-&quot; + mesi&#x5B;int(datafile.strftime(&quot;%m&quot;))-1]\n    return os.path.join(GiornoMese, file)\n\ndef is_image(file):\n    return os.path.splitext(file)&#x5B;1].lower() in img\n\ndef is_raw(file):\n    return os.path.splitext(file)&#x5B;1].lower() in imgraw\n\ndef is_video(file):\n    return os.path.splitext(file)&#x5B;1].lower() in video\n\ndef copia_file(HD, root, file):\n    cfile = os.path.join(root, file)\n    dest_path = get_dest_path(cfile, HD, file)\n    if os.path.exists(dest_path):\n        logging.info(f&quot;{file} - Gi\u00e0 Esistente.&quot;)\n        return False\n    else:\n        os.makedirs(os.path.dirname(dest_path), exist_ok=True)\n        shutil.copyfile(cfile, dest_path)\n        logging.info(f&quot;{file} - Copiato con successo in {dest_path}&quot;)\n        return True\n\nif __name__ == &quot;__main__&quot;:\n    main()\n\n<\/pre><\/div>","protected":false},"excerpt":{"rendered":"<p>Se sei come me, ogni volta che torni da un viaggio o da un evento speciale ti ritrovi con decine (o centinaia!) di foto sparse ovunque: sulla SD della fotocamera, sul telefono, magari anche sul cloud&#8230; E poi rimandiamo sempre il momento di organizzarle, finendo in un caos totale. Ecco perch\u00e9 ho deciso di creare &hellip; <\/p>\n<p class=\"link-more\"><a href=\"https:\/\/www.davidestecco.it\/it\/2025\/04\/14\/organizzare-le-foto-in-automatico-con-python-come-ho-creato-il-mio-photo-organizer\/\" class=\"more-link\">Leggi tutto<span class=\"screen-reader-text\"> &#8220;Organizzare le foto in automatico con Python: come ho creato il mio Photo Organizer&#8221;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[15],"tags":[],"class_list":["post-333","post","type-post","status-publish","format-standard","hentry","category-programmazione"],"_links":{"self":[{"href":"https:\/\/www.davidestecco.it\/it\/wp-json\/wp\/v2\/posts\/333","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.davidestecco.it\/it\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.davidestecco.it\/it\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.davidestecco.it\/it\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.davidestecco.it\/it\/wp-json\/wp\/v2\/comments?post=333"}],"version-history":[{"count":8,"href":"https:\/\/www.davidestecco.it\/it\/wp-json\/wp\/v2\/posts\/333\/revisions"}],"predecessor-version":[{"id":342,"href":"https:\/\/www.davidestecco.it\/it\/wp-json\/wp\/v2\/posts\/333\/revisions\/342"}],"wp:attachment":[{"href":"https:\/\/www.davidestecco.it\/it\/wp-json\/wp\/v2\/media?parent=333"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.davidestecco.it\/it\/wp-json\/wp\/v2\/categories?post=333"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.davidestecco.it\/it\/wp-json\/wp\/v2\/tags?post=333"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}