A python Script which syncs file names between


Recommended Posts

File Renamer 3.5

This is an app that chatGPT helped me create. I modified some of the code. It lets sync the file names from a source directory to a destination directory if both files are identical and all that was changed was the file's name. This way you don't have to recopy the file all over again.

  

image.png.1f2385aac718e66e8cea9ee662086188.png

image.png.333ff5cea13b2773f063816e4642f0b7.png

 

image.thumb.png.85d106e823e85362ddea018f6e334252.png

Version 3.5.1

  • Fixed a bug, where if a file had a specifically formatted file name it would get incorrectly renamed and shortened.

Change log

Version 3.5

Change log

  • Added the "Save folder paths" to save the file paths for both A and B
  • Added the "Load Folder Paths" to load the folder paths for A and B.

Version 3.1

Change log

  • Brand new UI
  • A save button to save the output of the scan
  • a progress bar
  • If a collision, all the files have been renamed, or there are no files found to be renamed you can't click Continue Renaming, the button is dead.
  • The scan results are now displayed in a table format
  • resizeable window
  • The words "collision found" appears in red at the top
  • All dialog boxes removed
  • The list of files is now scrollable

Version 2.3

Change log

  • Fixed a bug causing the app to hang while scanning a directory with 1000+ files
  • in the corruption detection, the text file now tells you the file (s)  in both A and B that caused the collision.

Version 2.0

Change log

  • After selecting A and B it checks both A and B for collisions and if any are found the program stops. If it finds collisions in either directory it saves the results of both directories to a folder on the desktop called collisions.txt. Once The collisions are fixed or if it doesn't find any the program proceeds Normally.
  • Changed the collision detection to look check the file name as well as the first word of the file name minus the extension. Plus the modified date and time from before.

 

import os
import re
import tkinter as tk
from tkinter import filedialog
from tkinter import messagebox
from tkinter import ttk

IGNORED_EXTENSIONS = ['.srt', '.nfo', '.sub']

def get_folder_path(entry):
    folder_path = filedialog.askdirectory()
    entry.delete(0, tk.END)
    entry.insert(0, folder_path)

def compare_folders():
    folder_a = folder_a_entry.get()
    folder_b = folder_b_entry.get()

    tree.delete(*tree.get_children())

    file_sizes_a = {}
    for filename in os.listdir(folder_a):
        if os.path.isfile(os.path.join(folder_a, filename)) and not filename.endswith(('.srt', '.nfo', '.sub')):
            file_sizes_a[filename] = os.path.getsize(os.path.join(folder_a, filename))

    file_names_b = []
    file_sizes_b = {}
    for filename in os.listdir(folder_b):
        if os.path.isfile(os.path.join(folder_b, filename)) and not filename.endswith(('.srt', '.nfo', '.sub')):
            file_names_b.append(filename)
            file_sizes_b[filename] = os.path.getsize(os.path.join(folder_b, filename))

    differences = []

    for filename_a, size_a in file_sizes_a.items():
        matched = False

        for filename_b, size_b in file_sizes_b.items():
            if size_a == size_b:
                name_b, ext_b = os.path.splitext(filename_b)

                if not re.search(r'\(\d{4}\)$', name_b):
                    differences.append((filename_a, filename_b))
                    matched = True
                    break

        
    for diff in differences:
        tree.insert('', 'end', values=diff)

    check_collisions(folder_b)  # Call check_collisions function after comparing folders

def check_collisions(folder_b):
    file_sizes = {}
    collisions = {}

    for filename in os.listdir(folder_b):
        file_extension = os.path.splitext(filename)[1].lower()

        if os.path.isfile(os.path.join(folder_b, filename)) and file_extension not in IGNORED_EXTENSIONS:
            size = os.path.getsize(os.path.join(folder_b, filename))

            if size in file_sizes:
                if size not in collisions:
                    collisions[size] = []
                collisions[size].extend([file_sizes[size], filename])
            else:
                file_sizes[size] = filename

    if collisions:
        report = "Collision Detected:\n\n"
        for size, filenames in collisions.items():
            report += f"Files with size {size} bytes:\n"
            report += " - ".join(filenames)
            report += "\n\n"

        messagebox.showwarning("Collision Detected", report)
    else:
        messagebox.showinfo("No Collisions", "No collisions found in the directory.")

def rename_files():
    folder_b = folder_b_entry.get()
    skipped_count = 0
    renamed_count = 0
    
    for child in tree.get_children():
        filename_a, filename_b = tree.item(child)['values']
        new_path = os.path.join(folder_b, filename_a)
        
        if not os.path.exists(new_path):
            os.rename(os.path.join(folder_b, filename_b), new_path)
            renamed_count += 1
        else:
            skipped_count += 1
    
    summary_message = f"Renamed files: {renamed_count}\nSkipped files: {skipped_count}"
    messagebox.showinfo('Renaming Summary', summary_message)

def save_folder_paths():
    folder_a = folder_a_entry.get()
    folder_b = folder_b_entry.get()

    save_path = filedialog.asksaveasfilename(defaultextension=".txt", filetypes=(("Text Files", "*.txt"), ("All Files", "*.*")))

    if save_path:
        with open(save_path, 'w') as file:
            file.write(f"Folder A: {folder_a}\n")
            file.write(f"Folder B: {folder_b}")

        messagebox.showinfo('Save', 'Folder paths saved successfully.')

def load_folder_paths():
    load_path = filedialog.askopenfilename(filetypes=(("Text Files", "*.txt"), ("All Files", "*.*")))

    if load_path:
        with open(load_path, 'r') as file:
            content = file.read()

        folder_a_match = re.search(r"Folder A: (.+)", content)
        folder_b_match = re.search(r"Folder B: (.+)", content)

        if folder_a_match and folder_b_match:
            folder_a = folder_a_match.group(1).strip()
            folder_b = folder_b_match.group(1).strip()

            folder_a_entry.delete(0, tk.END)
            folder_a_entry.insert(0, folder_a)
            folder_b_entry.delete(0, tk.END)
            folder_b_entry.insert(0, folder_b)

            messagebox.showinfo('Load', 'Folder paths loaded successfully.')
        else:
            messagebox.showwarning('Load', 'Invalid file format. Please select a valid text file.')

root = tk.Tk()

folder_a_entry = tk.Entry(root)
folder_a_entry.pack()
tk.Button(root, text="Use these names in Folder A", command=lambda: get_folder_path(folder_a_entry)).pack()

folder_b_entry = tk.Entry(root)
folder_b_entry.pack()
tk.Button(root, text="To rename files in this folder, Folder B", command=lambda: get_folder_path(folder_b_entry)).pack()

tk.Button(root, text="Compare Folders", command=compare_folders).pack()

tree = ttk.Treeview(root, columns=('Folder A', 'Folder B'), show='headings')
tree.heading('Folder A', text='Folder A')
tree.heading('Folder B', text='Folder B')
tree.pack(side='top', fill='both', expand=True, padx=10, pady=10)

tk.Button(root, text="Rename Files", command=rename_files).pack()

tk.Button(root, text="Save Folder Paths", command=save_folder_paths).pack()
tk.Button(root, text="Load Folder Paths", command=load_folder_paths).pack()

root.mainloop()

It's not difficult to understand, you've renamed the file so backup software is going to assume it's a new file. The contents of the file may be the same, but backup software isn't going to make assumptions like that. If you want incremental\checksum comparisons etc, the file is going to need to be the same name. Sure it may do some deduping in the background to compress the media set, but it is going to show the file with the amended file name.

If I have a media set, and files have been renamed, I want to be able to go back through the backup sets and see the differences, regardless if the file contents is the same.

You could write some PowerShell to compare the checksum of files in two locations; have it assume that if a file's checksum in Location A (source) matches that of a file in Location B (dest), rename file in Location B to match Location A, else copy file to location B.

 

You can try https://freefilesync.org/ with "content" method when comparing, haven't tried it. The other option is to go to you backup and rename them there as well manually before sync.

Update: Probably won't work if you are not using it already (before the rename) https://freefilesync.org/manual.php?topic=synchronization-settings - Detect Moved Files

  On 24/05/2023 at 05:23, binaryzero said:

You could write some PowerShell to compare the checksum of files in two locations; have it assume that if a file's checksum in Location A (source) matches that of a file in Location B (dest), rename file in Location B to match Location A, else copy file to location B.

Expand  

Already on it! I was Enlisting the help of chat GPT to write me some code.

So nailed out all the bugs and it works great

I wanted to do it properly by creating and comparing the hashes of the files but that brought my underpowered file server to its knees and it took forever given the file size. Plus I wanted to be able to do this over the network

I ended up having ChatGPT create a Python script that compares the first name of each file and the modification date in folder A (Source) and folder B (Destination). If it gets a match, it renames the file in folder B to the name of the file in folder A. This is because the file names will be all the same except for the year at the end of them

It then displays a box, showing me a before and after list of all the files it will be renaming and I have to confirm it. It will also skip files that are already named that name in folder B.

I on the first run it doubled up the file extension, so I told it to not do that and then it stopped doing that.

image.thumb.png.8bc8bdb60b48cb9584b2b01603c982a8.png

 

Once I click yes

image.thumb.png.28e45e47d004972b8a85c0cd4ce312f4.png

 

 

So I was trying to tell the program if it finds a file name with the same first word and the same date and time to skip it and move on but record it in a text file. But that made the code overly complicated and it didn't work.

so I thought let's have it make me a small collision detector .. the same first word same date AND same time. and ...

 

import os
import tkinter as tk
from tkinter import filedialog, messagebox
from collections import defaultdict

def get_first_word(file_name):
    return file_name.split('.')[0].split(' ')[0]

def find_file_collisions():
    folder_path = filedialog.askdirectory(title='Select Folder')

    if not folder_path:
        return

    file_info = defaultdict(list)
    collisions = []

    for file_name in os.listdir(folder_path):
        file_path = os.path.join(folder_path, file_name)

        if os.path.isfile(file_path):
            first_word = get_first_word(file_name)
            modified_time = os.path.getmtime(file_path)

            file_info[(first_word, modified_time)].append(file_path)

    for paths in file_info.values():
        if len(paths) > 1:
            collisions.extend(paths)

    if collisions:
        messagebox.showinfo("Collisions Found", "Collisions found in the directory.")

        desktop_path = os.path.join(os.path.expanduser("~"), "Desktop")
        file_path = os.path.join(desktop_path, "collisions.txt")
        with open(file_path, 'w') as file:
            file.write("Duplicate Files:\n")
            for path in collisions:
                file.write(f"{os.path.basename(path)} - {path}\n")

        messagebox.showinfo("Results Saved", f"Duplicate file names and paths recorded in {file_path}.")
    else:
        messagebox.showinfo("No Collisions", "No collisions found in the directory.")

# Create the main window
window = tk.Tk()
window.title('File Collision Detector')
window.geometry('400x200')

# Create the "Find Collisions" button
find_button = tk.Button(window, text='Find Collisions', command=find_file_collisions)
find_button.pack(pady=20)

# Run the main event loop
window.mainloop()

it worked great

I had it scan 1 of my directories it found 2 collisions.

2 files had the same first word in their name and both were modified on 10/27/2017 2:56 pm

So cool! Then I got a free program to change the modified date.

 

  On 25/05/2023 at 01:46, binaryzero said:

Cool.

Hopefully one day you learn how to code instead of relying on LLMs...

Expand  

Coding is not for me. I've attempted it many times. But I'm very happy an LLM wrote me some code to solve a problem I was having. The LLM was actually my last resort. I scoured around Google for a program to do what I wanted, but didn't find anything.

  • Like 3
  On 25/05/2023 at 07:19, Jose_49 said:

For massively renaming files I strongly recommend Bulk Rename Utility

It's daunting at first.

 

But after you get to know it. It will do wonders with your files!

Expand  

Yep, i've used it before. Great tool! Just not for right for This scenario.

  On 25/05/2023 at 20:18, Brandon H said:

neat. that's a surprisingly simple code base to achieve what you need there.

Expand  

Here is how the new version works.

First I run a small Collision finder app I had it make for me. This is because I was testing the first app by giving two files the exact same first name and modification date and time. To see what it would do, of course, the program didn't know how to handle it which I expected. I tried to tell it to add code to check for that into the program, but in the end, it was much easier for it to create a separate program I call Collision detector.

I actually ran the collision detector on the actual files I made this program for. It found some collisions. Super cool! in 2 of the cases they were duplicate files that could be removed. Gained back 9GB of data finding those.

image.thumb.png.264c19623c8afe513142214baeeff94a.pngimage.png.13b139b271a7ed56e1d93681043cb26e.png

image.png.020040de0f7b58f4d7dc5a1425c206fa.png

Or if it finds no duplicates it will say

image.png.b856cb549d8797dcf1f253fa9f9b1298.png

Now you can run the primary app

After you choose the source and destination it asks you if you want to save it to a text file. if you choose yes, it saves a text file called differences and then exits. Then go look at the text file first to see what it will be renaming.

image.thumb.png.da8a369e76be8048a81b9ce5a0bed785.png

image.thumb.png.b91de26e6c2d6df46e088e4c55570bb1.png

image.thumb.png.bff68285088f135639f0ab8a6a539fe9.png

Now once we are satisfied with what it will be renaming, we run the app again and choose no since we already examined the text file we can click yes to rename the files.

image.thumb.png.5f8ef5dba35cda5e1bbe9ad6d7211cfc.png

That's all there is to it!

 

image.png

  • +Warwagon changed the title to A python Script which syncs file names between
  • 2 weeks later...

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
  • Recently Browsing   0 members

    • No registered users viewing this page.
  • Posts

    • It's not. It's a rightwing lie peddled by liars to BillyBob'sFreedumb email chain. Feel free to provide any credible source to support this claim. You won't find a single one. The reason Biden wasn't prosecuted was because it was a handful of documents from the Obama years that were just in storage. And when the FBI asked for them, Biden and his team did everything they could to find them and return them immediately -- even ones the FBI didn't know were "missing". https://en.wikipedia.org/wiki/...assified_documents_incident Whereas the Charlatan in Chief stored mountains of classified material out in the open in his pay to play club infested with foreign spies. https://www.pbs.org/newshour/p...-mar-a-lago-shower-ballroom Trump also revealed this nation's most classified information to foreigners who had no clearance to access them...and then bragged about knowing them to their friends overseas. https://www.nbcnews.com/politi...arines-according-rcna119173 And not only are many still missing and not returned... https://www.cnn.com/interactiv...ssia-intelligence-trump-dg/ Trump denied having them to the FBI repeatedly and moved them around to avoid having to return them to the proper authorities for over a year. https://www.pbs.org/newshour/p...ing-of-classified-documents There is no credible legitimate comparison between the two classified documents cases. You might want to change the source of the information you are getting and falling for. They are quite obviously lying to you. PS On the content issue...I am a content creator. You and everyone else in the world loves the franchises and content I have created and/or contributed meaningfully to. It's the studios that are doing everything they can to remove us, the content creators, from their balance sheets (now with AI)...not the people who consume what we create for free. We've already been paid, thanks. Blame Wall Street for forcing the bottomless greedy enshittification of everything American, not the consumers, pirates, or the actual creators.
    • https://support.microsoft.com/...61ff-00a1-04e2-2d1f3865450d
    • https://support.microsoft.com/...61ff-00a1-04e2-2d1f3865450d
    • Swatle AI — the smarter way to manage your teams, projects, and tasks now 75% off by Steven Parker Today's highlighted deal comes via our Apps + Software section of the Neowin Deals store, where you can save 75% off on Swatle All-in-One AI Assistant (Premium lifetime subscription). Stop over-hiring and overspending to meet your productivity goals. Swatle is all you need to achieve more with less. Swatle is an all-in-one AI solution designed to supercharge your productivity without over-hiring or overspending. Whether you're managing projects, automating repetitive tasks, or organizing your team's workflow, Swatle can help you achieve more with less. Powered by cutting-edge artificial intelligence, it adapts to your needs, streamlines operations, and eliminates inefficiencies so you can focus on what matters most—growing your business. With Swatle, working smarter isn’t just a goal—it’s your new reality. Let Swatle AI handle the necessary mundane tasks. SWATLE AI PROJECT ASSISTANT Step-by-Step Guidance: For every task you assign, either write step-by-step instructions yourself or let Swatle AI write on your behalf Skip the Standups: Ask Swatle AI about project progress and get instant, actionable updates—no daily meetings needed Accurate Time Estimates: Plan your day better by estimating the time required to complete your tasks Message Refinement: Send crystal clear messages; Swatle AI will rephrase your message & make it crisp and clear Project Quality Boost: Turn normal project descriptions into a crystal-clear description TEAM COLLABORATION MADE EASY Streamline Communication: Send & receive messages and updates within Swatle for real-time, tool-free collaboration Centralized Team Portfolios: Create dedicated portfolios to highlight your team's expertise & track their contributions effectively Conversational Task Creation: Instantly create tasks while having casual conversations with a single click. Make sure nothing falls through the crack Share Files & Feedback Directly: Eliminate scattered documents and email threads by sharing files and providing feedback directly in Swatle chat SWATLE TASKDESK Non-Technical Projects: Specifically designed for projects like marketing campaigns, content creation, and event planning Visualize Work Your Way: Manage tasks through Kanban boards, lists, Gantt charts, or Timelines—whatever fits your flow AI Task Assistant: Break down complex tasks into manageable subtasks quickly & easily Workload Tracking: View the workload of your team members & distribute tasks across the team to encourage a balanced workload. Proactive Notifications: Effortlessly keep your projects on track with timely, proactive notifications SWATLE DEVBOARD Technical Projects: Create unlimited sprints & backlogs for full control and visibility into every phase of your projects Burndown Chart: Provides a clear, real-time visual representation of your team's work remaining against the sprint timeline Set Goals, Create Sprints, Achieve More: Define your objectives and launch focused sprints that empower your team to concentrate on key tasks within short, impactful cycles Why choose Swatle? No Learning Curve: Swatle offers a remarkably easy-to-use interface. Empower your entire team to understand project progress without requiring technical expertise. Actionable Intelligence: Swatle turns raw project data into visualizations, like Assigned vs Completed charts, enabling focused analysis without manual effort. Proactively Mitigate Risks: Swatle visual dashboards make it easy to spot potential delays, bottlenecks, and resource imbalances, enabling you to take timely action and keep your projects on track. Ensure Resources Are Optimized: By visualizing workloads, you can strategically distribute tasks, promote a balanced environment, and prevent team burnout. Maintain Project Alignment & Stakeholder Confidence: Keep everyone from your internal team to clients and stakeholders on the same page with clear Gantt and Timeline views. Good to know Length of access: lifetime Redemption deadline: redeem your code within 30 days of purchase Access options: desktop or mobile Max number of device(s): unlimited Available to both NEW and Existing users Updates included This Swatle All-in-One AI Assistant (Premium lifetime subscription) normally costs $240, but this deal can be yours for just $59.99, that's a saving of $180. For full terms, specifications, and license info please click the link below. Get this lifetime Swatle Premium deal for just $59.99 (75% off) or learn more Although priced in U.S. dollars, this deal is available for digital purchase worldwide. We post these because we earn commission on each sale so as not to rely solely on advertising, which many of our readers block. It all helps toward paying staff reporters, servers and hosting costs. Other ways to support Neowin Whitelist Neowin by not blocking our ads Create a free member account to see fewer ads Make a donation to support our day to day running costs Subscribe to Neowin - for $14 a year, or $28 a year for an ad-free experience Disclosure: Neowin benefits from revenue of each sale made through our branded deals site powered by StackCommerce.
  • Recent Achievements

    • First Post
      sultangris earned a badge
      First Post
    • Reacting Well
      sultangris earned a badge
      Reacting Well
    • First Post
      ClarkB earned a badge
      First Post
    • Week One Done
      Epaminombas earned a badge
      Week One Done
    • Week One Done
      Prestige Podiatry Care earned a badge
      Week One Done
  • Popular Contributors

    1. 1
      +primortal
      144
    2. 2
      Xenon
      127
    3. 3
      ATLien_0
      124
    4. 4
      +Edouard
      102
    5. 5
      snowy owl
      98
  • Tell a friend

    Love Neowin? Tell a friend!