Tool is executed in the album folder, preventing it from renaming it

How embarrassing, apparently I managed to bungle this test:

As it turns out, changing the working directory within the script is enough to not block the folder after all.

Tool:
Name: Folderrenamer
Path: C:\Users\<User>\AppData\Local\Programs\Python\Python312\python.exe
Parameter:
D:\PythonScripts\folderrenamer.py -d "$regexp(%_folderpath%,(.*)\\,$1)" --mp3tag -s
:ballot_box_with_check: for all selected files

Combining this with a filter like %track% IS 1 OR %track% IS 01 to only run it once per directory works as intended as you can see.
folderrenamer

Sorry for wasting your time, everyone!

In case some of you want to try my script, here's the current version.
It requires Python, ffmpeg on PATH, Mp3tag on PATH and tqdm (pip3 install tqdm) and if you want to run it anywhere from the CLI instead of as an Mp3tag tool, I recommend adding the script (or the script folder) to PATH as well. There are many guides how you can add something to PATH.

WARNING:
Only use it from the CLI if you know what you're doing. Since it recursively scans and renames folders, you could very easily rename program folders that happen to have audio files in them if you execute it in the wrong directory! As a Mp3tag tool it's limited to renaming the folder of the file that you call it on.

Should someone want/need further explanations (basic usage instructions are available via -h or --help) I can add the script to github and write documentation. This is simply the version I use.

folderrenamer.py
import os
import sys
import subprocess
import re
import argparse
from tqdm import tqdm
from collections import defaultdict

# List of supported audio file extensions
AUDIO_EXTENSIONS = {"flac", "mp3", "m4a", "ogg"}

def parse_arguments():
    def dir_path(path):
        if os.path.isdir(path) and path != None:
            return path
        else:
            raise argparse.ArgumentTypeError(f"readable_dir:{path} is not a valid path")
        
    parser = argparse.ArgumentParser(description='Rename folder(s) based on the properties of contained audio files and append the format(s) in square brackets.')
    parser.add_argument('-d', '--directory',
                        help='The directory that will be scanned for audio files and renamed based on their properties.', type=dir_path, default=".", const=".", nargs="?")
    parser.add_argument('--mp3tag', action='store_true',
                        help='Add the renamed folders to Mp3tag. Press F5 in Mp3tag afterwards to refresh the file list.')
    parser.add_argument('-s', '--single_folder', action='store_true',
                        help='Only scan a single folder for audio files and rename it.')

    args: argparse.Namespace = parser.parse_args()

    return args

def extract_audio_properties(file_path):
    """
    Extracts the bitrate, bit depth, sampling rate, and number of channels from an audio file using ffprobe.
    """
    try:
        result = subprocess.run(
            [
                'ffprobe', '-v', 'error', '-select_streams', 'a:0',
                '-show_entries', 'stream=bit_rate,sample_rate,bits_per_raw_sample,channels',
                '-of', 'default=noprint_wrappers=1:nokey=1', file_path
            ],
            stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True
        )
        
        values = result.stdout.split('\n')
        bitrate = int(values[2]) // 1000 if values[2].isdigit() else None  # convert from bps to kbps
        sampling_rate = int(values[0]) if values[0].isdigit() else None
        bit_depth = int(values[3]) if values[3].isdigit() else None
        channels = int(values[1]) if values[1].isdigit() else None
        
        return bitrate, sampling_rate, bit_depth, channels
    except Exception as e:
        print(f"Error extracting properties from {file_path}: {e}")
        return None, None, None, None

def analyze_folder(folder_path):
    """
    Analyzes the audio files in a folder, collecting file types and audio properties.
    """
    properties = defaultdict(list)  # Structure: {filetype: [(bitrate, sampling_rate, bit_depth, channels)]}
    mixed_formats = set()
    
    for file in os.listdir(folder_path):
        file_ext = os.path.splitext(file)[-1][1:].lower()
        
        if file_ext in AUDIO_EXTENSIONS:
            file_path = os.path.join(folder_path, file)
            bitrate, sampling_rate, bit_depth, channels = extract_audio_properties(file_path)
            if bitrate or sampling_rate or bit_depth or channels:
                properties[file_ext].append((bitrate, sampling_rate, bit_depth, channels))
            mixed_formats.add(file_ext.upper())
    
    return properties, mixed_formats

def format_folder_name(base_name, properties, mixed_formats):
    """
    Generate the new folder name based on the audio properties and file types found.
    """
    if len(mixed_formats) > 2:  # Don't needlessly bloat the filename with more than 2 formats
        return f"{base_name} [MIXED FORMATS]"

    # Define the custom order for formats
    format_priority = {"flac": 1, "mp3": 2, "m4a": 3, "ogg": 4}
    parts = []

    # Process FLAC files first, sorted by descending quality
    for filetype, prop_list in sorted(properties.items(), key=lambda x: format_priority.get(x[0], float('inf'))):
        if filetype == 'flac':
            flac_variants = []
            for bitrate, sampling_rate, bit_depth, channels in sorted(
                set(prop_list), key=lambda x: (-x[2], -x[1], -x[3] if x[3] else 0)
            ):
                variant_parts = [f"{bit_depth}", f"{sampling_rate / 1000:g}"]  # Convert Hz to kHz
                if channels and channels > 2:
                    channel_map = {3: "2.1", 6: "5.1", 8: "7.1"}
                    variant_parts.append(channel_map.get(channels, str(channels)))

                flac_variants.append("-".join(variant_parts))

            parts.append(f"FLAC {', '.join(flac_variants)}")
        else:
            # Process other formats (e.g., MP3, M4A, OGG)
            bitrates = sorted(set(bitrate for bitrate, _, _, _ in prop_list if bitrate), reverse=True)
            if bitrates:
                if len(bitrates) > 1:
                    all_bitrates = [bitrate for bitrate, _, _, _ in prop_list if bitrate]
                    avg_bitrate = round(sum(all_bitrates) / len(all_bitrates))
                if len(bitrates) == 1:
                    parts.append(f"{filetype.upper()} {bitrates[0]}")
                else:
                    parts.append(f"{filetype.upper()} {bitrates[-1]}-{bitrates[0]} ⌀{avg_bitrate}")
    # Skip renaming folders that only contain CD quality FLAC files
    if parts and parts != ["FLAC 16-44.1"]:
        return f"{base_name} [{', '.join(parts)}]"
    else:
        return base_name

def main(args):
    directory = args.directory
    single_folder = args.single_folder
    mp3tag = args.mp3tag
    if mp3tag: os.chdir("..")
    match_folder = re.compile(r"^(.*) \[(?:FLAC [\d,⌀ .-]+)?(?:MP3 [\d,⌀ .-]+)?(?:M4A [\d,⌀ .-]+)?(?:OGG [\d,⌀ .-]+)?\]$|^(.*) \[MIXED FORMATS\]$")
    renamed = 0
    skipped = 0
    renamed_folders = []

    """
    Recursively processes subfolders in the given base path, analyzing audio properties and renaming folders accordingly.
    """
    if not single_folder:
        with tqdm(desc="Scanning and renaming folders.", unit=" folders", ncols=100) as pbar:

            for root, dirs, files in os.walk(directory, topdown=False):  # Bottom-up to rename folders after processing their contents
                folder_name = os.path.basename(root)
                parent_path = os.path.dirname(root)

                # Check if the folder has already been renamed
                match = re.match(match_folder, folder_name)
                base_name = match.group(1) or match.group(2) if match else folder_name

                properties, mixed_formats = analyze_folder(root)
                if not mixed_formats:
                    continue
                new_folder_name = format_folder_name(base_name, properties, mixed_formats)
                
                if new_folder_name != folder_name:  # Compare to the original folder name
                    new_path = os.path.join(parent_path, new_folder_name)
                    try:
                        os.rename(root, new_path)
                        pbar.update(1)
                        renamed+=1
                        pbar.set_postfix({"renamed": renamed}, {"skipped": skipped})
                        renamed_folders.append(os.path.abspath(new_path))
                    except Exception as e:
                        print(f"Error renaming folder {root} to {new_path}: {e}")
                else:
                    pbar.update(1)
                    skipped+=1
                    pbar.set_postfix({"renamed": renamed}, {"skipped": skipped})

    else:
        folder_name = os.path.basename(directory)
        parent_path = os.path.dirname(directory)

        # Check if the folder has already been renamed
        match = re.match(match_folder, folder_name)
        base_name = match.group(1) or match.group(2) if match else folder_name

        properties, mixed_formats = analyze_folder(directory)
        if not mixed_formats:
            print ("No music files found in the folder, exiting.")
            sys.exit()
        new_folder_name = format_folder_name(base_name, properties, mixed_formats)
        
        if new_folder_name != folder_name:  # Compare to the original folder name
            new_path = os.path.join(parent_path, new_folder_name)
            try:
                os.rename(directory, new_path)
                print(f"Renamed: {directory} -> {new_path}")
                renamed_folders.append(os.path.abspath(new_path))
            except Exception as e:
                print(f"Error renaming folder {directory} to {new_path}: {e}")
    if mp3tag and renamed_folders:
        for folder in renamed_folders:
            try:
                subprocess.run(["mp3tag", "/add", f'/fp:"{folder}"'])
            except subprocess.CalledProcessError:
                print(f"Error while adding {folder} to Mp3tag.")
    # Uncomment when you want to inspect the output
    #input("Press Enter to continue...")

if __name__ == "__main__":
    args = parse_arguments()
    try:
        main(args)
    except KeyboardInterrupt:
        print("Interrupted")
        try:
            sys.exit(130)
        except SystemExit:
            os._exit(130)