I found a Python script that does the job: https://github.com/im-PJs/GoPro-File-Organizer/tree/main:
# Author: https://github.com/im-PJs
import os
import shutil
import sys
from collections import defaultdict
def organize_files(base_path):
# Count occurrences of each file number for .MP4 files
mp4_count = defaultdict(int)
file_paths = defaultdict(list)
# First pass to collect file information
for filename in os.listdir(base_path):
if filename.endswith(('.MP4', '.LRV', '.THM')):
file_number = filename[4:8]
file_paths[file_number].append(filename)
if filename.endswith('.MP4'):
mp4_count[file_number] += 1
# Save original paths before moving
with open(os.path.join(base_path, 'original_paths.txt'), 'w') as f:
# Second pass to move files if there are multiple MP4s with the same number
for file_number, files in file_paths.items():
if mp4_count[file_number] > 1: # Create folder only if more than one MP4 file with the same number
folder_name = f"Video_{file_number}"
folder_path = os.path.join(base_path, folder_name)
if not os.path.exists(folder_path):
os.makedirs(folder_path)
for filename in files:
original_path = os.path.join(base_path, filename)
new_path = os.path.join(folder_path, filename)
shutil.move(original_path, new_path)
print(f"Moved '{filename}' to '{new_path}'")
f.write(f"{new_path}={original_path}\n")
def undo_organization(base_path):
paths_file = os.path.join(base_path, 'original_paths.txt')
if not os.path.exists(paths_file):
print("No organization to undo.")
return
# Read the original paths and move files back
with open(paths_file, 'r') as file:
for line in file:
new_path, original_path = line.strip().split('=')
shutil.move(new_path, original_path)
print(f"Moved '{new_path}' back to '{original_path}'")
# Remove empty folders
for folder in os.listdir(base_path):
folder_path = os.path.join(base_path, folder)
if os.path.isdir(folder_path) and not os.listdir(folder_path):
os.rmdir(folder_path)
print(f"Removed empty folder: {folder_path}")
os.remove(paths_file)
print("Undo complete.")
if __name__ == "__main__":
# Use the current directory as the base directory
base_directory = os.getcwd()
if len(sys.argv) > 1 and sys.argv[1] == '-undoLast':
undo_organization(base_directory)
else:
organize_files(base_directory)
Tested on Windows 10 21H2 Pro with Python 3.11.9, running python main.py
.
Before:
(test) N:\GoPro\test>tree /F
Folder PATH listing for volume 2024GoPro
Volume serial number is 0746-89B1
N:.
main.py
GL010356.LRV
GL020356.LRV
GL030356.LRV
GX010356.MP4
GX010356.THM
GX020356.MP4
GX020356.THM
GX030356.MP4
GX030356.THM
GL010355.LRV
GL020355.LRV
GL030355.LRV
GL040355.LRV
GX010355.MP4
GX010355.THM
GX020355.MP4
GX020355.THM
GX030355.MP4
GX030355.THM
GX040355.MP4
GX040355.THM
GL010357.LRV
GL020357.LRV
GL030357.LRV
GL040357.LRV
GL050357.LRV
GX010357.MP4
GX010357.THM
GX020357.MP4
GX020357.THM
GX030357.MP4
GX030357.THM
GX040357.MP4
GX040357.THM
GX050357.MP4
GX050357.THM
No subfolders exist
After:
N:.
│ main.py
│ original_paths.txt
│
├───Video_0356
│ GL010356.LRV
│ GL020356.LRV
│ GL030356.LRV
│ GX010356.MP4
│ GX010356.THM
│ GX020356.MP4
│ GX020356.THM
│ GX030356.MP4
│ GX030356.THM
│
├───Video_0355
│ GL010355.LRV
│ GL020355.LRV
│ GL030355.LRV
│ GL040355.LRV
│ GX010355.MP4
│ GX010355.THM
│ GX020355.MP4
│ GX020355.THM
│ GX030355.MP4
│ GX030355.THM
│ GX040355.MP4
│ GX040355.THM
│
└───Video_0357
GL010357.LRV
GL020357.LRV
GL030357.LRV
GL040357.LRV
GL050357.LRV
GX010357.MP4
GX010357.THM
GX020357.MP4
GX020357.THM
GX030357.MP4
GX030357.THM
GX040357.MP4
GX040357.THM
GX050357.MP4
GX050357.THM
To undo the file move: python main.py -undoLast