<p>I found a Python script that does the job: <a href="https://github.com/im-PJs/GoPro-File-Organizer/tree/main" rel="nofollow noreferrer">https://github.com/im-PJs/GoPro-File-Organizer/tree/main</a>:</p>
<pre><code># 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] &gt; 1:  # Create folder only if more than one MP4 file with the same number
                folder_name = f&quot;Video_{file_number}&quot;
                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&quot;Moved '{filename}' to '{new_path}'&quot;)
                    f.write(f&quot;{new_path}={original_path}\n&quot;)

def undo_organization(base_path):
    paths_file = os.path.join(base_path, 'original_paths.txt')
    
    if not os.path.exists(paths_file):
        print(&quot;No organization to undo.&quot;)
        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&quot;Moved '{new_path}' back to '{original_path}'&quot;)
    
    # 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&quot;Removed empty folder: {folder_path}&quot;)

    os.remove(paths_file)
    print(&quot;Undo complete.&quot;)

if __name__ == &quot;__main__&quot;:
    # Use the current directory as the base directory
    base_directory = os.getcwd()
    if len(sys.argv) &gt; 1 and sys.argv[1] == '-undoLast':
        undo_organization(base_directory)
    else:
        organize_files(base_directory)    
</code></pre>
<p>Tested on Windows 10 21H2 Pro with Python 3.11.9, running <code>python main.py</code>.</p>
<p>Before:</p>
<pre><code>(test) N:\GoPro\test&gt;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
</code></pre>
<p>After:</p>
<pre><code>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
</code></pre>
<p>To undo the file move: <code>python main.py -undoLast</code></p>

CC BY-SA 4.0
2024-11-03T07:07:49.057Z
2024-11-03T07:07:49.057Z
Franck Dernoncourt
<p>By default, GoPro recordings are saved in one folder, and recordings are cut into several files as shown below:</p>
<p>Recording ID 356:</p>
<ul>
<li>GX010356.MP4</li>
<li>GX020356.MP4</li>
<li>GX030356.MP4</li>
<li>GX040356.MP4</li>
</ul>
<p>Recording ID 357:</p>
<ul>
<li>GX010357.MP4</li>
<li>GX020357.MP4</li>
<li>GX030357.MP4</li>
</ul>
<p>That stupid naming convention makes it hard to select all files of the same recording, since sorting files <a href="https://i.sstatic.net/ZktCwkmS.png" rel="nofollow noreferrer">doesn't help</a>.</p>
<p>How to group GoPro videos by folder?</p>
<p>E.g., I want all the files of Recording ID 356:</p>
<ul>
<li>GX010356.MP4</li>
<li>GX020356.MP4</li>
<li>GX030356.MP4</li>
<li>GX040356.MP4</li>
</ul>
<p>in folder <code>356</code>, and all the files of Recording ID 357:</p>
<ul>
<li>GX010357.MP4</li>
<li>GX020357.MP4</li>
<li>GX030357.MP4</li>
</ul>
<p>in folder <code>357</code>.</p>

<gopro>
How to group GoPro recordings by folder?
Franck Dernoncourt
# How to group GoPro recordings by folder?

(Asked by: username_0 on 2024-11-03)

By default, GoPro recordings are saved in one folder, and recordings are cut into several files as shown below:

Recording ID 356:

* GX010356.MP4
* GX020356.MP4
* GX030356.MP4
* GX040356.MP4

Recording ID 357:

* GX010357.MP4
* GX020357.MP4
* GX030357.MP4

That stupid naming convention makes it hard to select all files of the same recording, since sorting files [doesn't help](https://i.sstatic.net/ZktCwkmS.png).

How to group GoPro videos by folder?

E.g., I want all the files of Recording ID 356:

* GX010356.MP4
* GX020356.MP4
* GX030356.MP4
* GX040356.MP4

in folder `356`, and all the files of Recording ID 357:

* GX010357.MP4
* GX020357.MP4
* GX030357.MP4

in folder `357`.

**Tags:** gopro


---

## 1 answers

### Answer by username_0 on 2024-11-03. Score: 0

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


---

