constrig Ierakstīts Februāris 16 Share Ierakstīts Februāris 16 Sveiki! Vai ir kāda bezmaksas utīla priekš Win, ar kuras palīdzību iespējams sameklēt, nofiltrēt foto (no visiem failiem kas uz diska) definējot konkrētu datumu, datu avotam jābūt no exif (create date) datiem. Līdzīgi, kā Onedrive (Memory Pictures) to dara. Paldies Link to comment Share on other sites More sharing options...
Vilx Februāris 16 Share Februāris 16 Kādreiz vai tikai Irfanview kaut ko tādu nemācēja, plus tam ir kaudze pluginu, gan jau kāds māk to ko vajag. Link to comment Share on other sites More sharing options...
Boņs Februāris 16 Share Februāris 16 (labots) Ehh, zirgā sēž un zirgu meklē Paver File explorer un search laukā iesit DateTaken:20.09.2023 vai kādu tur vajag. Vienīgā nianse, ka datorā var atšķirties reģionālie settingi, tāpēc jāpārslēdz explorera skatu Details režīmā (view poga) un datuma/laika formātu var pašpikot no Date modified lauka. Vēl Details skatā var uzklikšķināt uz aiļu galvenes (column header) ar žurkas labo pogu un pielikt Date created lauku (spied pa priekšu More), pēc kura varēsi šķirot. Rezultāts abām darbībām aptuveni šāds: Labots Februāris 16 - Boņs 2 Link to comment Share on other sites More sharing options...
constrig Februāris 16 Author Share Februāris 16 Boņs variants neder, jo tie nebūs EXIF dati (faktiskais bildēšanas datums atšķiras no faila izveides datuma) Link to comment Share on other sites More sharing options...
AndrisBB Februāris 16 Share Februāris 16 (labots) Var jau pielikt 'Date Taken' kolonu un paskatīties vai tas sakrīt ar 'Date Created'. Kas to zin ko Windows File Explorers dara, bet uz Mac parasti kad kopē failus no kameras/telefona, tad viņš ieliek 'Date Created' nevis, kad fails tika pārkopēts, bet izvelk no EXIF. Labots Februāris 16 - AndrisBB Link to comment Share on other sites More sharing options...
HIGH-Zen Februāris 16 Share Februāris 16 Ja citi varianti neder, tad var uzrakstīt Python skriptu. Link to comment Share on other sites More sharing options...
binary Februāris 16 Share Februāris 16 1 stundu atpakaļ, constrig teica: Boņs variants neder, jo tie nebūs EXIF dati (faktiskais bildēšanas datums atšķiras no faila izveides datuma) Kas tad tie būs, ja ne EXIF dati? 1 Link to comment Share on other sites More sharing options...
HIGH-Zen Februāris 16 Share Februāris 16 pirms 2 stundām , constrig teica: Boņs variants neder Der, der (Windows 11): Link to comment Share on other sites More sharing options...
constrig Februāris 17 Author Share Februāris 17 Jā, sory, taisnība. LV win variantā meklēšanas laukā jāraksta "uzņemšanasdatums:16/02/2002" bet man nepieciešams konkrēta datuma uzņemtās bildes ne tikai vienā 2002 gadā, bet no 2002. līdz 2024. gadam. pirms 18 stundām , HIGH-Zen teica: Ja citi varianti neder, tad var uzrakstīt Python skriptu. kādas izmaksas izdarīt augstāk minēto, pretstatā gatavam produktam? Link to comment Share on other sites More sharing options...
Aigus Februāris 17 Share Februāris 17 Kādu kreiso bezmaksas sameklēt neļauj ticība? 😁 1 Link to comment Share on other sites More sharing options...
HIGH-Zen Februāris 17 Share Februāris 17 (labots) 1 stundu atpakaļ, constrig teica: kādas izmaksas izdarīt augstāk minēto, pretstatā gatavam produktam? Viena pēcpusdiena. Uz mani neskaties, man nav laika, tagad mācos LISP. Vēl vienkāršāks veids ar NO, LĪDZ datumiem var meklēt iekš Double Commander. Alt+F7 -> File mask = *.jpg -> Advanced -> Date form, Date to. Feed to Listbox. Labots Februāris 17 - HIGH-Zen Link to comment Share on other sites More sharing options...
binary Februāris 17 Share Februāris 17 (labots) Pirms 16 minūtēm , HIGH-Zen teica: Vēl vienkāršāks veids ar NO, LĪDZ datumiem var meklēt iekš Double Commander. Viņš prot EXIF? 1 stundu atpakaļ, constrig teica: bet man nepieciešams konkrēta datuma uzņemtās bildes ne tikai vienā 2002 gadā, bet no 2002. līdz 2024. gadam. Katra gada konkrētā datumā? "*.jpg datetaken:*-01-01 datetaken:>=2002" (vai kāds nu tev tur ir tas formāts) nestrādā? Labots Februāris 17 - binary Link to comment Share on other sites More sharing options...
HIGH-Zen Februāris 17 Share Februāris 17 (labots) Pirms 50 minūtēm , binary teica: Viņš prot EXIF? Man (uz Windows 11) .jpg failiem Date laukā rāda datumu no EXIF. Notestēju uz sava datora, viss darbojas. Edit: Uzbraucot ar peli virs bildes tā arī rāda - Date taken. Edit2: Patestēju vēl. Iekš Double Commander Date laukā rāda - Date Modified. Ja bilde nav labota kopš uzņemšanas, tad "Date Modified" sakrīt ar "Date taken". Windows Explorer jebkurā gadījumā rāda "Date Taken". Atlasīt Windows Explorer-ī no - līdz var ar šādu sintaksi: DateTaken:14.01.2021 .. 05.05.2023 Labots Februāris 17 - HIGH-Zen Link to comment Share on other sites More sharing options...
kurtka Februāris 17 Share Februāris 17 (labots) Runājot par python skriptiem, uzreiz nāca prātā ChatGPT. Par vai nepar- brīnumu šis iedeva kodu, kas praktiski darbojās out-of-the-box, vajadzēja tikai datuma formātu izlabot. Nedarbojas, ja beigu datums sakrīt ar sākuma datumu, bet to visu var tūnēt. Šajā redakcijā izmanto exif 'data-taken' info. Pirmo redakciju šis izveidoja ar faila 'data created' info. Apm 15 min mana laika. Paldies par iemeslu paprokrastinēt pie man neaktuālas problēmas, tikai lai pārbaudītu savu hipotēzi Darbinu ar VSCode: import os import shutil from datetime import datetime from PIL import Image def get_exif_date_taken(image_path): try: with Image.open(image_path) as img: exif_data = img._getexif() if exif_data: date_taken = exif_data.get(36867) # 36867 corresponds to the 'DateTimeOriginal' tag if date_taken: return datetime.strptime(date_taken, "%Y:%m:%d %H:%M:%S") except (AttributeError, KeyError, IndexError): pass return None def filter_and_copy_photos(source_folder, destination_folder, start_date, end_date): # Convert start_date and end_date strings to datetime objects start_date = datetime.strptime(start_date, "%d.%m.%Y") end_date = datetime.strptime(end_date, "%d.%m.%Y") # Create destination folder if it doesn't exist if not os.path.exists(destination_folder): os.makestāsti(destination_folder) # Initialize the count of copied photos copied_photos_count = 0 # Iterate through files in the source folder for filename in os.listdir(source_folder): file_path = os.path.join(source_folder, filename) # Check if the file is a photo (you can customize this check based on your file types) if os.path.isfile(file_path) and any(file_path.lower().endswith(ext) for ext in ['.jpg', '.jpeg', '.png']): # Get the date taken from EXIF data date_taken = get_exif_date_taken(file_path) # Check if the file has EXIF data and if the date is within the specified range if date_taken and start_date <= date_taken <= end_date: # Copy the file to the destination folder shutil.copy2(file_path, os.path.join(destination_folder, filename)) copied_photos_count += 1 # Print the number of copied photos print(f"Number of photos copied: {copied_photos_count}") # Example usage: source_folder = "d:/##__FOTO__##/zz_Test_photos/" destination_folder = "d:/##__FOTO__##/zz_Test_photos_filtered/" start_date = "04.04.2022" end_date = "05.04.2022" filter_and_copy_photos(source_folder, destination_folder, start_date, end_date) Labots Februāris 17 - kurtka 3 Link to comment Share on other sites More sharing options...
AndrisBB Februāris 17 Share Februāris 17 Pirms 11 minūtēm , kurtka teica: os.makestāsti(destination_folder) Pat kodā forums neļauj lamāties 😂 3 Link to comment Share on other sites More sharing options...
versatile Februāris 17 Share Februāris 17 Jēdzīgāk ir tiešām kāds foto meneģeris, kas veido savu db ar metadatiem. Uz sitienu nepateikšu, šķiet, xnview vai faststone kko tādu prata, bet neesmu drošs. Link to comment Share on other sites More sharing options...
kurtka Februāris 17 Share Februāris 17 (labots) Pirms 11 minūtēm , AndrisBB teica: Pat kodā forums neļauj lamāties 😂 Un neļauj labot! Foruma cenzūras tests: makestāsti='makestāsti'? 'maked.i.r.s'='maked.i.r.s' yap. Ja kāds vispār tik tālu tiek: 25. rindā 'os.makestāsti' vietā ir jābūt 'os.maked.i.r.s' bez punktiem. Fenomenāla foruma cenzūra :D, paldies @AndrisBB Labots Februāris 17 - kurtka Link to comment Share on other sites More sharing options...
binary Februāris 17 Share Februāris 17 (labots) pirms 1 stundas , HIGH-Zen teica: Ja bilde nav labota kopš uzņemšanas, tad "Date Modified" sakrīt ar "Date taken". Tas atkarīgs no aparatūras. No Canon fotoaparāta kopēju bildes, liekot SD karti datorā - tad sakrita. No Sony kopēju caur kabeli, jo tur īpatnēja folderu struktūra uz kartes. Tam, šķiet, faila "izveides" laiku rāda, kad fails ir kopēts no fotoaparāta. Neesmu vēl saņēmies uzrakstīt python skriptu, kas faila laikus no ienādotu ar tiem exif datiem... Labots Februāris 17 - binary Link to comment Share on other sites More sharing options...
camel Februāris 17 Share Februāris 17 Xnview MP ir iespēja Show Files in Subfolders, Sort by EXIF date taken, tālāk jau vieglāk meklēt Link to comment Share on other sites More sharing options...
raiviic Februāris 17 Share Februāris 17 (labots) pirms 2 stundām , binary teica: Tam, šķiet, faila "izveides" laiku rāda, kad fails ir kopēts no fotoaparāta Gan Sony, gan Canon tā rāda General sadaļā, pie tam vēlāk bildi kaut kur pārkopējot jebkurai bildei mainās , bet zem Details viss saglabājas pareizi. Labots Februāris 17 - raiviic Link to comment Share on other sites More sharing options...
binary Februāris 17 Share Februāris 17 (labots) @raiviic, es par to spriedu pēc tā, ka Total Commander "mass rename" fīča no viena aparāta ņemtajām bildēm mācēja "pareizo" datumu izvilkt, no cita aparāta nē. Tā fīča izmanto faila "metadatus" (tos, kas glabājas failu sistēmā), nevis exif (glabājas pašā failā). Kurš tieši no tiem laikiem tur saglabājās "pareizais" (created, modified vai kāds cits) - nav ne jausmas. Zinu tik, ka, atkarībā no aparatūras, tie datumi vai nu atbilst fotografēšanas laikam, vai arī "izvilkšanas no afotoaparāta" laikam. Labots Februāris 17 - binary Link to comment Share on other sites More sharing options...
AndrisBB Februāris 17 Share Februāris 17 (labots) pirms 2 stundām , binary teica: No Canon fotoaparāta kopēju bildes, liekot SD karti datorā - tad sakrita. No Sony kopēju caur kabeli, jo tur īpatnēja folderu struktūra uz kartes. Tam, šķiet, faila "izveides" laiku rāda, kad fails ir kopēts no fotoaparāta. Tas tākā loģiski. Pirmajā gadījumā fotoaparāts uztaisija failu uz SD kartes, ar reālu failu sistēmu un attribūtiem. DateCreated un dati iekš Exif +- sakritīs (kad fotoaparāts saglabāja failu uz SD kartes), ja nu vienīgi kāda milisekunde atšķirība. Pārkopējot uz PC no kartes, izmantojas tas pats DateCreated. Otrajā gadījumā kopējot caur kabeli, nav gluži kopēšana no vienas FS uz citu (kautvai kautkādā softā izskatās ka ir), fails tiek izveidots pa jaunam. Tapēc arī DateCreated ir, tad kad pārkopē. Iespējams ka protokols ko Sony izmanto 'caur vadu' nemaz neatbalsta kautkādus 'papildus' failu metadatus, aka datumus utt, tikai izmēru un nosaukumu. Tapēc arī PC izmanto datumu, kad tika pārkopēts. Labots Februāris 17 - AndrisBB 1 Link to comment Share on other sites More sharing options...
AndrisBB Februāris 17 Share Februāris 17 (labots) Plus iekš Windows ir arī atšķirība starp copy/paste un cut/paste (vienā gadījumā datums mainīsies, otrā saglabāsies) Labots Februāris 17 - AndrisBB Link to comment Share on other sites More sharing options...
nrs Februāris 19 Share Februāris 19 Atbildod uz sākotnējo jautājumu, lai varētu redzēt bildes no konkrētā mēneša un dienas, bet visus gadus, man ir tikai viens, diezgan čakarīgs variants. Noskanē folderi, kur ir visas bildes ar exiftool. Komanda manā gadījumā "exiftool -DateTimeOriginal -n -r -csv -progress "C:\Users\inorm\JOB_no_cld\ni\Pictures\- Apsekosana -" > mbildes.csv". Tālāk imports excelī. Excelī izveido papildus kolonnas Mēnesis un otra kolonna Diena. Tālāk filtrs pa vajadzīgo mēneša dienu. Tad nokopē filelist, iekopē, piemēram, txt. Importē ar xnview. Otrs variants atver txt ar jpgview, tik tad / jāpārvēš uz \. Link to comment Share on other sites More sharing options...
rubb Februāris 19 Share Februāris 19 TotalCommander + EXIF addons netiek apsvērts? TotalCommander var uzlikt arī triāli. EXIF addons ļauj izskatā ielikt kolonnu, kurā attēlo faila exif datus. Link to comment Share on other sites More sharing options...
nrs Februāris 19 Share Februāris 19 Pirms šo rakstīju, pamocīju to TC ar eif addoniem. Bet nē, nekas tur nesanāk. Augstākais ko var izveidot, arī Mēneša un diena kolonnas, bet tās nesortējas un nefiltrējas. Link to comment Share on other sites More sharing options...
Usins Februāris 19 Share Februāris 19 man patīk šie interesantie laiki, kad dažkārt ātrāk un saprotamāk ir ar AI palīdzību uzrakstīt python vai citu skriptu, kā izburties cauri win search sintaksei vai pārējo softu specifikai. Link to comment Share on other sites More sharing options...
rubb Februāris 19 Share Februāris 19 56 minutes ago, nrs said: Bet nē, nekas tur nesanāk. Rāda OK, sakrīt ar EXIF Date Taken, arī kārtojas OK. Link to comment Share on other sites More sharing options...
nrs Februāris 19 Share Februāris 19 Un kā tālāk atlasīsi 22. februāra bildes arī no 2004, 2007, 2010 etc gadiem, kā contric ir vajadzīgs? Link to comment Share on other sites More sharing options...
nrs Februāris 19 Share Februāris 19 Zinu ļoti labi šo find tūli TC. Tik tas atrod konkrēta gada.men.dienas bildi. Bet Atrodi visus gadus 22.februāri, piemēram? Neizdosies. Link to comment Share on other sites More sharing options...
binary Februāris 19 Share Februāris 19 Wildcards neprot? T.i., gada vietā "*"? Link to comment Share on other sites More sharing options...
HIGH-Zen Februāris 19 Share Februāris 19 (labots) Augstāk minētais ChatGPT python kods lasa bildes no vienas mapes. Ja vajag rekursīvi visām apakšmapēm, tad tāds nederēs. Edit: Vispār būtu interesanti uzzināt autora domas - kuru pieeju galu galā viņš izvēlējās. Labots Februāris 19 - HIGH-Zen Link to comment Share on other sites More sharing options...
AndrisBB Februāris 19 Share Februāris 19 Pirms 21 minūtēm , HIGH-Zen teica: Augstāk minētais ChatGPT python kods lasa bildes no vienas mapes. Ja vajag rekursīvi visām apakšmapēm, tad tāds nederēs. Vaitad grūti uzprasīt tam pašam ChatGPT lai iekļauj arī apakšmapes? Link to comment Share on other sites More sharing options...
Usins Februāris 19 Share Februāris 19 (labots) papildināju ar apakšmapēm un brutālu tkinter interface. datumu ievadīju tajos logos dd.mm.yyyy darbojās, bet beigās nokārās, nebija laika pētīt kādēļ, minu, ka uzrāvās uz dropbox failu kurš tiek lejupielādēts pēc pieprasījuma, bet explorer izskatās, ka ir. ar šiem python skripti nesadarbojas labi. edit: zemāk aktuālāks Labots Februāris 19 - Usins Link to comment Share on other sites More sharing options...
AndrisBB Februāris 19 Share Februāris 19 Te jau gandrīz vai Git repo jātaisa, lai 'interesējošie' var papildināt funkcionalitāti 😂 Link to comment Share on other sites More sharing options...
camel Februāris 19 Share Februāris 19 Papildus kopēšanai varētu pievienot iespēju veidot shortcutus vai symbolic linkus (hard linkus), vai var papildināt metadatus ar kautkādiem keywords un tad jau var izmantot piemēram XnViewMP meklēšanai pēc keywordiem ... Link to comment Share on other sites More sharing options...
Usins Februāris 19 Share Februāris 19 (labots) ekhm, tagad ignorē failus, kas nav lokāli diskā, bet dropbox mākonī, kā arī failus kuriem exif tukšs. pievienoju opciju meklēt jebkādus failus. iespēja meklēt 16. feb katru gadu darbojas glīti. 'stop' poga bija izaicinājums, darbojas. mēģināju noexportēt kā .exe priekš normāliem cilvēkiem, vēl nesāca. visu rakstīja GPT4, tik cik viņu bakstīju. kas viņam tipiski - neoptimālas diska operācijas, rakstīt log uz katru failu. visdrīzāk pie šī vēl piestrādāšu (kādreiz, varbūt), jo ļoti riebjas windows meklēšana. import os import shutil from datetime import datetime import tkinter as tk from tkinter import filedialog, Label, Button, Entry, Checkbutton, IntVar, ttk # Import ttk for combobox from tkcalendar import DateEntry from PIL import Image import threading # Shared variable to control the process stop_requested = False def get_exif_date_taken(image_path): try: with Image.open(image_path) as img: exif_data = img._getexif() if exif_data: date_taken = exif_data.get(36867) # 36867 corresponds to the 'DateTimeOriginal' tag if date_taken: return datetime.strptime(date_taken, "%Y:%m:%d %H:%M:%S") except (AttributeError, KeyError, IndexError): pass return None def filter_and_copy_photos(source_folder, destination_folder, start_date, end_date, include_subfolders, this_period_every_year, date_type, file_types): global stop_requested # Reset stop_requested in case it was set in a previous run stop_requested = False start_date = datetime.strptime(start_date, "%d.%m.%Y") end_date = datetime.strptime(end_date, "%d.%m.%Y") if not os.path.exists(destination_folder): os.makestāsti(destination_folder) copied_photos_count = 0 skipped_files = [] if include_subfolders: for root, stāsti, files in os.walk(source_folder): for filename in files: if stop_requested: break file_path = os.path.join(root, filename) # Now correctly passing file_types to process_file process_file(file_path, start_date, end_date, destination_folder, copied_photos_count, skipped_files, this_period_every_year, date_type, file_types) else: for filename in os.listdir(source_folder): if stop_requested: break file_path = os.path.join(source_folder, filename) # Again, make sure to pass file_types to process_file process_file(file_path, start_date, end_date, destination_folder, copied_photos_count, skipped_files, this_period_every_year, date_type, file_types) log_skipped_files(skipped_files) print(f"Number of photos copied: {copied_photos_count}") print(f"Number of files skipped: {len(skipped_files)}") def process_file(file_path, start_date, end_date, destination_folder, copied_photos_count, skipped_files, this_period_every_year, date_type, file_types): try: # Split the custom file types string into a list file_extensions = file_types.split(',') if os.path.isfile(file_path) and any(file_path.lower().endswith(ext) for ext in file_extensions): if not os.path.getsize(file_path) > 0: raise IOError("File is online-only or empty") date_taken = get_file_date(file_path, date_type) if date_taken and is_date_in_range(date_taken, start_date, end_date, this_period_every_year): shutil.copy2(file_path, os.path.join(destination_folder, os.path.basename(file_path))) copied_photos_count += 1 else: raise ValueError("Missing or invalid date data") except (IOError, ValueError) as e: skipped_files.append(file_path) print(f"Skipped file (Reason - {e}): {file_path}") def log_skipped_files(skipped_files): # Check if logging is enabled if log_skipped_var.get() == 1: with open("skipped_files_log.txt", "w") as log_file: for file_path in skipped_files: log_file.write(f"{file_path}\n") def select_folder(label): folder_selected = filedialog.askdirectory() label.config(text=folder_selected) return folder_selected def threaded_filter_and_copy(): start_date_str = start_date_entry.get_date().strftime('%d.%m.%Y') end_date_str = end_date_entry.get_date().strftime('%d.%m.%Y') filter_and_copy_photos(source_label['text'], destination_label['text'], start_date_entry.get(), end_date_entry.get(), subfolders_var.get(), this_period_var.get(), date_option_var.get(), file_types_entry.get()) def run_filter(): # Starting the filter process in a separate thread threading.Thread(target=threaded_filter_and_copy).start() def is_date_in_range(date_taken, start_date, end_date, this_period_every_year): if this_period_every_year: # Adjust the year of the date taken to match the start date for comparison date_taken_adjusted = date_taken.replace(year=start_date.year) return start_date <= date_taken_adjusted <= end_date else: return start_date <= date_taken <= end_date def get_file_date(file_path, date_type): if date_type == 'date_modified': return datetime.fromtimestamp(os.path.getmtime(file_path)) elif date_type == 'date_created': return datetime.fromtimestamp(os.path.getctime(file_path)) elif date_type == 'exif_date_taken': return get_exif_date_taken(file_path) else: return None def stop_process(): global stop_requested stop_requested = True root = tk.Tk() root.title("File search by date and copy") source_label = Label(root, text="Select source folder") source_label.pack() Button(root, text="Browse", command=lambda: select_folder(source_label)).pack() destination_label = Label(root, text="Select destination folder") destination_label.pack() Button(root, text="Browse", command=lambda: select_folder(destination_label)).pack() start_date_label = tk.Label(root, text="Date from (included):") start_date_label.pack() start_date_entry = DateEntry(root, date_pattern='dd.mm.yyyy') start_date_entry.pack() end_date_label = tk.Label(root, text="Date to (NOT included):") end_date_label.pack() end_date_entry = DateEntry(root, date_pattern='dd.mm.yyyy') end_date_entry.pack() subfolders_var = IntVar() Checkbutton(root, text="Include subfolders", variable=subfolders_var).pack() this_period_var = IntVar() Checkbutton(root, text="This period every year", variable=this_period_var).pack() # Define the options for the dropdown menu date_options = ['date_modified', 'date_created', 'exif_date_taken'] date_option_var = tk.StringVar() date_option_dropdown = ttk.Combobox(root, textvariable=date_option_var, values=date_options) date_option_dropdown.current(0) # Default to the first option ('date_modified') date_option_dropdown.pack() # Add label for file types entry file_types_label = tk.Label(root, text="Enter file types, comma separated (e.g., jpg,jpeg,png):") file_types_label.pack() # Add entry widget for file types file_types_entry = tk.Entry(root) file_types_entry.pack() # Frame to hold Start and Stop buttons buttons_frame = tk.Frame(root) buttons_frame.pack(fill=tk.X, pady=5) # Start Filtering Button start_button = tk.Button(buttons_frame, text="Start Filtering", command=run_filter) start_button.pack(side=tk.LEFT, padx=(10, 5), expand=True) # Stop Button stop_button = tk.Button(buttons_frame, text="Stop", command=stop_process) stop_button.pack(side=tk.LEFT, padx=(5, 10), expand=True) # Variable to track the checkbox state (1 for checked, 0 for unchecked) log_skipped_var = tk.IntVar() # Create the checkbox log_skipped_checkbox = tk.Checkbutton(root, text="Write log for skipped files (not optimal disk usage)", variable=log_skipped_var) log_skipped_checkbox.pack() root.mainloop() Labots Februāris 19 - Usins 2 Link to comment Share on other sites More sharing options...
nrs Februāris 19 Share Februāris 19 @Usins, vai pareizi saprotu, ka tas skripts vai programma aizkopē konkrētās dienas failus uz atsevišķu folderi? Tādā gadījumā, tas man liekas diezgan neērts risinājums. Vai nevar uzstaisīt, ka tas skripts rada bilžu sourcefile sarakstu notepadā? To tālāk var atvērt jau ar daudziem vīveriem, bez čakara kopēt un dzēst lielus MB vai GB. Otra lieta, kāda ir ātrdarbība? Piemēram, mans personiskais bilžu folderis pa 20 gadiem ir izaudzis līdz 100 000 bildēm un 200GB. Ja pie katra meklējuma jāpavada pusstunda, stunda, arī garām. Tad jau labāk vienreiz sataisi sarakstu ar exiftool, un manipulē datus ar exceli vai acesu, tā teikt, vienā rāvienā. Bet ja ātrdarbība nav problēma, tad tā programmiņa būtu noderīgs, izmantojams risinājums. Link to comment Share on other sites More sharing options...
Usins Februāris 19 Share Februāris 19 exe sanāca, bet tam trūka vizualizācijas progresam, ko līdz šim nodrošināja python outputs. esmu jauki pavadījis laiku ar GPT. Jāatzīst GPT4 python raksta glīti, reti ir erroru kuru rezultātā kods nedarbojas. Ir daudz pārpratumu, vai 'sekla uzdevuma izpilde' neiedziļinoties būtībā Un pieeja necensties rīkoties optimāli ar datora resursiem. Vajadzēs pašam palūgt konspektu, ko šovakar esmu 'iemācijies'. papildināts ar counter un current folder, lai var saprast ka darbojas. import os import shutil from datetime import datetime import tkinter as tk from tkinter import filedialog, Label, Button, Entry, Checkbutton, IntVar, ttk # Import ttk for combobox from tkcalendar import DateEntry from PIL import Image import threading root = tk.Tk() root.title("File search by date and copy") # Shared variable to control the process stop_requested = False processed_files_var = tk.StringVar() current_folder_var = tk.StringVar() def get_exif_date_taken(image_path): try: with Image.open(image_path) as img: exif_data = img._getexif() if exif_data: date_taken = exif_data.get(36867) # 36867 corresponds to the 'DateTimeOriginal' tag if date_taken: return datetime.strptime(date_taken, "%Y:%m:%d %H:%M:%S") except (AttributeError, KeyError, IndexError): pass return None def filter_and_copy_photos(source_folder, destination_folder, start_date, end_date, include_subfolders, this_period_every_year, date_type, file_types): global stop_requested # Reset stop_requested in case it was set in a previous run stop_requested = False start_date = datetime.strptime(start_date, "%d.%m.%Y") end_date = datetime.strptime(end_date, "%d.%m.%Y") if not os.path.exists(destination_folder): os.makestāsti(destination_folder) copied_photos_count = 0 skipped_files = [] # Nested function to update the GUI def update_status(folder, count): # Safely update the GUI from the main thread using root.after. root.after(0, lambda: processed_files_var.set(f"Processed files: {count}")) root.after(0, lambda: current_folder_var.set(f"Current folder: {folder}")) # Begin processing the files try: if include_subfolders: for root_dir, stāsti, files in os.walk(source_folder): # Check if stop has been requested if stop_requested: break update_status(root_dir, copied_photos_count) # Update the status for the current folder for filename in files: if stop_requested: break file_path = os.path.join(root_dir, filename) # Existing file processing logic process_file(file_path, start_date, end_date, destination_folder, copied_photos_count, skipped_files, this_period_every_year, date_type, file_types) copied_photos_count += 1 # Increment the copied photos count update_status(root_dir, copied_photos_count) # Update the GUI with the current count else: # Process files in the source folder if not including subfolders for filename in os.listdir(source_folder): if stop_requested: break file_path = os.path.join(source_folder, filename) # Existing file processing logic process_file(file_path, start_date, end_date, destination_folder, copied_photos_count, skipped_files, this_period_every_year, date_type, file_types) copied_photos_count += 1 # Increment the copied photos count update_status(source_folder, copied_photos_count) # Update the GUI with the current count finally: # When the process is stopped or completed, update the GUI accordingly update_status("Stopped" if stop_requested else "Completed", copied_photos_count) # Log the skipped files if needed log_skipped_files(skipped_files) print(f"Number of photos copied: {copied_photos_count}") print(f"Number of files skipped: {len(skipped_files)}") def process_file(file_path, start_date, end_date, destination_folder, copied_photos_count, skipped_files, this_period_every_year, date_type, file_types): try: # Split the custom file types string into a list file_extensions = file_types.split(',') if os.path.isfile(file_path) and any(file_path.lower().endswith(ext) for ext in file_extensions): if not os.path.getsize(file_path) > 0: raise IOError("File is online-only or empty") date_taken = get_file_date(file_path, date_type) if date_taken and is_date_in_range(date_taken, start_date, end_date, this_period_every_year): shutil.copy2(file_path, os.path.join(destination_folder, os.path.basename(file_path))) copied_photos_count += 1 else: raise ValueError("Missing or invalid date data") except (IOError, ValueError) as e: skipped_files.append(file_path) print(f"Skipped file (Reason - {e}): {file_path}") def log_skipped_files(skipped_files): # Check if logging is enabled if log_skipped_var.get() == 1: with open("skipped_files_log.txt", "w") as log_file: for file_path in skipped_files: log_file.write(f"{file_path}\n") def select_folder(label): folder_selected = filedialog.askdirectory() label.config(text=folder_selected) return folder_selected def threaded_filter_and_copy(): start_date_str = start_date_entry.get_date().strftime('%d.%m.%Y') end_date_str = end_date_entry.get_date().strftime('%d.%m.%Y') filter_and_copy_photos(source_label['text'], destination_label['text'], start_date_entry.get(), end_date_entry.get(), subfolders_var.get(), this_period_var.get(), date_option_var.get(), file_types_entry.get()) def run_filter(): # Starting the filter process in a separate thread threading.Thread(target=threaded_filter_and_copy).start() def is_date_in_range(date_taken, start_date, end_date, this_period_every_year): if this_period_every_year: # Adjust the year of the date taken to match the start date for comparison date_taken_adjusted = date_taken.replace(year=start_date.year) return start_date <= date_taken_adjusted <= end_date else: return start_date <= date_taken <= end_date def get_file_date(file_path, date_type): if date_type == 'date_modified': return datetime.fromtimestamp(os.path.getmtime(file_path)) elif date_type == 'date_created': return datetime.fromtimestamp(os.path.getctime(file_path)) elif date_type == 'exif_date_taken': return get_exif_date_taken(file_path) else: return None def stop_process(): global stop_requested stop_requested = True source_label = Label(root, text="Select source folder") source_label.pack() Button(root, text="Browse", command=lambda: select_folder(source_label)).pack() destination_label = Label(root, text="Select destination folder") destination_label.pack() Button(root, text="Browse", command=lambda: select_folder(destination_label)).pack() start_date_label = tk.Label(root, text="Date from (included):") start_date_label.pack() start_date_entry = DateEntry(root, date_pattern='dd.mm.yyyy') start_date_entry.pack() end_date_label = tk.Label(root, text="Date to (NOT included):") end_date_label.pack() end_date_entry = DateEntry(root, date_pattern='dd.mm.yyyy') end_date_entry.pack() subfolders_var = IntVar() Checkbutton(root, text="Include subfolders", variable=subfolders_var).pack() this_period_var = IntVar() Checkbutton(root, text="This period every year", variable=this_period_var).pack() # Define the options for the dropdown menu date_options = ['date_modified', 'date_created', 'exif_date_taken'] date_option_var = tk.StringVar() date_option_dropdown = ttk.Combobox(root, textvariable=date_option_var, values=date_options) date_option_dropdown.current(0) # Default to the first option ('date_modified') date_option_dropdown.pack() # Add label for file types entry file_types_label = tk.Label(root, text="Enter file types, comma separated (e.g., jpg,jpeg,png):") file_types_label.pack() # Add entry widget for file types file_types_entry = tk.Entry(root) file_types_entry.pack() # Frame to hold Start and Stop buttons buttons_frame = tk.Frame(root) buttons_frame.pack(fill=tk.X, pady=5) # Start Filtering Button start_button = tk.Button(buttons_frame, text="Start Filtering", command=run_filter) start_button.pack(side=tk.LEFT, padx=(10, 5), expand=True) # Stop Button stop_button = tk.Button(buttons_frame, text="Stop", command=stop_process) stop_button.pack(side=tk.LEFT, padx=(5, 10), expand=True) # Variable to track the checkbox state (1 for checked, 0 for unchecked) log_skipped_var = tk.IntVar() # Create the checkbox log_skipped_checkbox = tk.Checkbutton(root, text="Write log for skipped files (not optimal disk usage)", variable=log_skipped_var) log_skipped_checkbox.pack() processed_files_label = tk.Label(root, textvariable=processed_files_var) processed_files_label.pack() current_folder_label = tk.Label(root, textvariable=current_folder_var) current_folder_label.pack() root.mainloop() te, (uz mana datora LOL) strādājošs exe. https://www.dropbox.com/scl/fi/g0heaqkn8y5ro27xbt41t/search_files_by_dates_pick.exe?rlkey=fvsc4g87l302l47q8uqlxusr8&dl=0 šitam tagad loga izmērs raustās pieskaņojoties aktuālā foldera nosaukuma garumam, Link to comment Share on other sites More sharing options...
Recommended Posts
Izveido kontu, vai pieraksties esošajā, lai komentētu
Jums ir jābūt šī foruma biedram, lai varētu komentēt tēmas
Izveidot jaunu kontu
Piereģistrējies un izveido jaunu kontu, tas būs viegli!
Reģistrēt jaunu kontuPierakstīties
Jums jau ir konts? Pierakstieties tajā šeit!
Pierakstīties tagad!