From 33a0815d5cbfea2a730fd150f16315ad53ffec22 Mon Sep 17 00:00:00 2001 From: Georg Brantegger Date: Sat, 20 Jun 2026 19:51:23 +0200 Subject: [PATCH] added script to rename files in videoanalyse folder, so that they are easiert to navigate --- Nextcloud Video Files/rename_files.ipynb | 149 +++++++++++++++++++++++ package_loader.py | 2 + 2 files changed, 151 insertions(+) create mode 100644 Nextcloud Video Files/rename_files.ipynb diff --git a/Nextcloud Video Files/rename_files.ipynb b/Nextcloud Video Files/rename_files.ipynb new file mode 100644 index 0000000..aeac2f9 --- /dev/null +++ b/Nextcloud Video Files/rename_files.ipynb @@ -0,0 +1,149 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "id": "1b3ec01f", + "metadata": {}, + "outputs": [], + "source": [ + "# ===== CONFIGURATION =====\n", + "# --- Configuration ---\n", + "NEXTCLOUD_URL = \"https://nextcloud.karnelegger.eu\"\n", + "USERNAME = \"Georg Brantegger\"\n", + "with open('app_pw.txt','r') as f:\n", + " APP_PASSWORD = f.readline()\n", + "\n", + "\n", + "# Modern Nextcloud WebDAV endpoint format:\n", + "WEBDAV_BASE_URL = f\"{NEXTCLOUD_URL}/remote.php/dav/files/{USERNAME}/Shared/Ruderverein/02_Athlet:innen/01_Videoanalyse\"\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "c1f60f39", + "metadata": {}, + "outputs": [], + "source": [ + "import os\n", + "from nc_py_api import Nextcloud\n", + "\n", + "def rename_videos_via_api():\n", + " # Initialize the Nextcloud client\n", + " nc = Nextcloud(\n", + " nextcloud_url=NEXTCLOUD_URL, \n", + " nc_auth_user=USERNAME, \n", + " nc_auth_pass=APP_PASSWORD\n", + " )\n", + "\n", + " # The path to your shared folder relative to your user's root\n", + " base_folder = \"Shared/Ruderverein/02_Athlet:innen/01_Videoanalyse\" \n", + "\n", + " print(f\"Fetching folders from: {base_folder}...\")\n", + " \n", + " # 1. Get all items in the base directory\n", + " try:\n", + " items_in_base = nc.files.listdir(base_folder)\n", + " except Exception as e:\n", + " print(f\"Error accessing base folder: {e}\")\n", + " return\n", + "\n", + " # Filter for directories only (the athlete subfolders)\n", + " athlete_folders = [item for item in items_in_base if item.is_dir]\n", + "\n", + " for folder in athlete_folders:\n", + " print(f\"\\nProcessing athlete: {folder.name}\")\n", + "\n", + " # 2. Gather files inside the athlete's folder\n", + " folder_contents = nc.files.listdir(folder.user_path)\n", + " \n", + " # Gather all valid files (ignoring directories and hidden files)\n", + " all_files = [f for f in folder_contents if not f.is_dir and not f.name.startswith('.')]\n", + "\n", + " if not all_files:\n", + " print(\" No files found. Skipping.\")\n", + " continue\n", + "\n", + " # Lists to separate files we want to rename\n", + " files_to_rename = []\n", + "\n", + " # 1. Check for XMLs to delete, and separate the rest for renaming\n", + " for file_node in all_files:\n", + " extension = os.path.splitext(file_node.name)[1].lower()\n", + " \n", + " if extension == '.xml':\n", + " print(f\" -> šŸ—‘ļø Deleting XML: {file_node.name}\")\n", + " nc.files.delete(file_node.user_path)\n", + " else:\n", + " files_to_rename.append(file_node)\n", + "\n", + " # If there were only XMLs and now nothing is left, move to the next athlete\n", + " if not files_to_rename:\n", + " continue\n", + "\n", + " # 2. Sort the remaining files by modification date\n", + " files_to_rename.sort(key=lambda x: x.info._last_modified)\n", + " new_filenames =[x.info._last_modified.strftime('%Y-%m-%d_%H-%M-%S') for x in files_to_rename]\n", + "\n", + "\n", + " # 4. Safety Step: Rename to temporary names to avoid collisions\n", + " temp_files = []\n", + " for index, file_node in enumerate(files_to_rename):\n", + " # Extract the directory path and the original file extension\n", + " directory, old_filename = os.path.split(file_node.user_path)\n", + " extension = os.path.splitext(old_filename)[1]\n", + " \n", + " temp_name = f\"__temp_{index}__{extension}\"\n", + " temp_path = f\"{directory}/{temp_name}\"\n", + " \n", + " # In Nextcloud/WebDAV APIs, renaming a file is executed as a \"move\" command\n", + " nc.files.move(file_node.user_path, temp_path)\n", + " temp_files.append((temp_path, extension, old_filename))\n", + "\n", + " # 5. Final Rename: Apply the sequential counting names\n", + " for index, (temp_path, extension, old_filename) in enumerate(temp_files, start=1):\n", + " directory, _ = os.path.split(temp_path)\n", + " new_name = f\"{new_filenames[index-1]}{extension}\"\n", + " final_path = f\"{directory}/{new_name}\"\n", + " \n", + " i = 1\n", + " try:\n", + " nc.files.move(temp_path, final_path)\n", + " print(f\" -> Renamed {old_filename} to {new_name}\")\n", + " except:\n", + " new_name = f\"{new_filenames[index-1]}_{i}{extension}\"\n", + " final_path = f\"{directory}/{new_name}\"\n", + " nc.files.move(temp_path, final_path)\n", + " i += 1\n", + " print(f\" -> Renamed {old_filename} to {new_name}\")\n", + "\n", + " print(\"\\nāœ… All athlete folders have been processed via the API!\")\n", + "\n", + "if __name__ == \"__main__\":\n", + " rename_videos_via_api()" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": ".venv (3.14.4.final.0)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.14.4" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/package_loader.py b/package_loader.py index ba19882..b29c7ec 100644 --- a/package_loader.py +++ b/package_loader.py @@ -21,6 +21,8 @@ def get_list_of_packages_to_load(): packages.append('requests') packages.append('openpyxl') packages.append('jinja2') # for styling + packages.append('nc-py-api') + packages.append('urllib3') # packages.append('matplotlib') # packages.append('pyqt5')