Mit diesem Python-Skript kannst du das Änderungsdatum und die Uhrzeit eines Ordners sowie aller darin enthaltenen Dateien und Unterordner rekursiv anpassen. Unter Windows lässt sich optional auch die Erstellungszeit umschreiben.
#!/usr/bin/env python3
# *****************************************************************************
# Grafische Oberfläche (PyQt6) zum Ändern von Datum und Uhrzeit
# eines Ordners und aller darin enthaltenen Dateien und Unterordner.
# Installation der Abhängigkeit: pip install PyQt6
# Start: python datum_aendern_gui.py
# (c) Hans Busche Datum: 03.07.2026
# *****************************************************************************
import os
import sys
import time
import platform
from datetime import datetime
from PyQt6.QtCore import Qt, QThread, pyqtSignal, QDateTime
from PyQt6.QtWidgets import (
QApplication,
QMainWindow,
QWidget,
QVBoxLayout,
QHBoxLayout,
QLabel,
QLineEdit,
QPushButton,
QFileDialog,
QDateTimeEdit,
QCheckBox,
QTextEdit,
QProgressBar,
QMessageBox,
)
# *****************************************************************************
# Logik zum Setzen der Zeitstempel.
# Setzt unter Windows zusätzlich die Erstellungszeit (benötigt pywin32).
# *****************************************************************************
def set_creation_time_windows(pfad: str, ziel_zeit: datetime):
if platform.system() != "Windows":
return
try:
import pywintypes
import win32file
import win32con
wintime = pywintypes.Time(ziel_zeit)
flags = win32con.FILE_FLAG_BACKUP_SEMANTICS if os.path.isdir(pfad) else 0
handle = win32file.CreateFile(
pfad,
win32con.GENERIC_WRITE,
0,
None,
win32con.OPEN_EXISTING,
flags,
None,
)
win32file.SetFileTime(handle, wintime, None, None)
handle.close()
except ImportError:
pass
except Exception:
pass
# *****************************************************************************
# Hilfsfunktion für "set_creation_time_windows"
# *****************************************************************************
def setze_zeit(pfad: str, timestamp: float, ziel_zeit: datetime, mit_erstellungszeit: bool):
os.utime(pfad, (timestamp, timestamp))
if mit_erstellungszeit:
set_creation_time_windows(pfad, ziel_zeit)
# *****************************************************************************
# Thread! Damit die GUI während der Verarbeitung nicht einfriert.
# Wenn ein Ordner sehr viele Dateien enthält, würde das Ändern aller Zeiten ein
# paar Sekunden dauern
# *****************************************************************************
class Worker(QThread):
fortschritt = pyqtSignal(int, int) # aktuell, gesamt
log = pyqtSignal(str)
fertig = pyqtSignal(int, int, list) # anzahl_dateien, anzahl_ordner, fehler
def __init__(self, ordner: str, ziel_zeit: datetime, mit_erstellungszeit: bool):
super().__init__()
self.ordner = ordner
self.ziel_zeit = ziel_zeit
self.mit_erstellungszeit = mit_erstellungszeit
def run(self):
timestamp = time.mktime(self.ziel_zeit.timetuple())
fehler = []
# Erst alle Pfade sammeln, damit die Fortschrittsanzeige stimmt
alle_pfade = []
for wurzel, unterordner, dateien in os.walk(self.ordner, topdown=False):
for datei in dateien:
alle_pfade.append(os.path.join(wurzel, datei))
for sub in unterordner:
alle_pfade.append(os.path.join(wurzel, sub))
alle_pfade.append(self.ordner)
gesamt = len(alle_pfade)
anzahl_dateien = 0
anzahl_ordner = 0
for i, pfad in enumerate(alle_pfade, start=1):
try:
setze_zeit(pfad, timestamp, self.ziel_zeit, self.mit_erstellungszeit)
if os.path.isdir(pfad):
anzahl_ordner += 1
self.log.emit(f"Ordner aktualisiert: {pfad}")
else:
anzahl_dateien += 1
self.log.emit(f"Datei aktualisiert: {pfad}")
except Exception as e:
fehler.append(f"{pfad}: {e}")
self.log.emit(f"FEHLER bei '{pfad}': {e}")
self.fortschritt.emit(i, gesamt)
self.fertig.emit(anzahl_dateien, anzahl_ordner, fehler)
# *****************************************************************************
# Fenster! PyQt6-spezifisch.
# *****************************************************************************
class HauptFenster(QMainWindow):
def __init__(self):
super().__init__()
self.setWindowTitle("Ordner, Datei(en), Unterordner: Datum & Uhrzeit ändern")
self.setMinimumWidth(600)
self.worker = None
zentral = QWidget()
self.setCentralWidget(zentral)
layout = QVBoxLayout(zentral)
# --- Ordnerauswahl ---
ordner_layout = QHBoxLayout()
ordner_layout.addWidget(QLabel("Ordner:"))
self.ordner_feld = QLineEdit()
self.ordner_feld.setPlaceholderText("Ordner auswählen …")
ordner_layout.addWidget(self.ordner_feld)
durchsuchen_btn = QPushButton("Durchsuchen …")
durchsuchen_btn.clicked.connect(self.ordner_waehlen)
durchsuchen_btn.setStyleSheet(
"""
QPushButton {
background-color: #b8b55c;
color: white;
font-size: 15px;
font-weight: bold;
border-radius: 6px;
padding: 8px 16px;
}
QPushButton:hover {
background-color: #4f4d0b;
}
QPushButton:pressed {
background-color: #1b5e20;
}
QPushButton:disabled {
background-color: #a5d6a7;
color: #eeeeee;
}
"""
)
ordner_layout.addWidget(durchsuchen_btn)
layout.addLayout(ordner_layout)
# --- Datum/Uhrzeit-Auswahl ---
datum_layout = QHBoxLayout()
datum_layout.addWidget(QLabel("Ziel-Datum/Uhrzeit:"))
self.datum_feld = QDateTimeEdit()
self.datum_feld.setCalendarPopup(True)
self.datum_feld.setDisplayFormat("dd.MM.yyyy HH:mm:ss")
self.datum_feld.setDateTime(QDateTime.currentDateTime())
datum_layout.addWidget(self.datum_feld)
layout.addLayout(datum_layout)
# --- Optionen ---
self.erstellungszeit_checkbox = QCheckBox(
"Erstellungszeit ebenfalls setzen (nur Windows, benötigt pywin32)"
)
if platform.system() != "Windows":
self.erstellungszeit_checkbox.setEnabled(False)
self.erstellungszeit_checkbox.setToolTip(
"Nur unter Windows verfügbar."
)
layout.addWidget(self.erstellungszeit_checkbox)
# --- Start-Button ---
self.start_btn = QPushButton("Datum/Uhrzeit setzen")
self.start_btn.clicked.connect(self.starten)
self.start_btn.setCursor(Qt.CursorShape.PointingHandCursor)
self.start_btn.setMinimumHeight(45)
self.start_btn.setStyleSheet(
"""
QPushButton {
background-color: #2e7d32;
color: white;
font-size: 15px;
font-weight: bold;
border-radius: 6px;
padding: 8px 16px;
}
QPushButton:hover {
background-color: #388e3c;
}
QPushButton:pressed {
background-color: #1b5e20;
}
QPushButton:disabled {
background-color: #a5d6a7;
color: #eeeeee;
}
"""
)
layout.addWidget(self.start_btn)
# --- Fortschrittsbalken ---
self.fortschritt_balken = QProgressBar()
layout.addWidget(self.fortschritt_balken)
# --- Log-Ausgabe ---
layout.addWidget(QLabel("Protokoll:"))
self.log_ausgabe = QTextEdit()
self.log_ausgabe.setReadOnly(True)
layout.addWidget(self.log_ausgabe)
def ordner_waehlen(self):
ordner = QFileDialog.getExistingDirectory(self, "Ordner auswählen")
if ordner:
self.ordner_feld.setText(ordner)
def starten(self):
ordner = self.ordner_feld.text().strip()
if not ordner or not os.path.isdir(ordner):
QMessageBox.warning(self, "Fehler", "Bitte einen gültigen Ordner auswählen.")
return
qdatetime = self.datum_feld.dateTime()
ziel_zeit = datetime(
qdatetime.date().year(),
qdatetime.date().month(),
qdatetime.date().day(),
qdatetime.time().hour(),
qdatetime.time().minute(),
qdatetime.time().second(),
)
antwort = QMessageBox.question(
self,
"Bestätigung",
f"Datum/Uhrzeit von allen Dateien und Unterordnern in\n\n"
f"'{ordner}'\n\n"
f"wird auf {ziel_zeit.strftime('%d.%m.%Y %H:%M:%S')} gesetzt.\n\n"
f"Fortfahren?",
QMessageBox.StandardButton.Yes | QMessageBox.StandardButton.No,
)
if antwort != QMessageBox.StandardButton.Yes:
return
self.log_ausgabe.clear()
self.fortschritt_balken.setValue(0)
self.start_btn.setEnabled(False)
mit_erstellungszeit = self.erstellungszeit_checkbox.isChecked()
self.worker = Worker(ordner, ziel_zeit, mit_erstellungszeit)
self.worker.fortschritt.connect(self.fortschritt_aktualisieren)
self.worker.log.connect(self.log_ausgabe.append)
self.worker.fertig.connect(self.verarbeitung_fertig)
self.worker.start()
def fortschritt_aktualisieren(self, aktuell: int, gesamt: int):
if gesamt > 0:
self.fortschritt_balken.setMaximum(gesamt)
self.fortschritt_balken.setValue(aktuell)
def verarbeitung_fertig(self, anzahl_dateien: int, anzahl_ordner: int, fehler: list):
self.start_btn.setEnabled(True)
meldung = f"Fertig!\n{anzahl_dateien} Datei(en) und {anzahl_ordner} Ordner aktualisiert."
if fehler:
meldung += f"\n\n{len(fehler)} Fehler aufgetreten (siehe Protokoll)."
self.log_ausgabe.append("\n" + meldung)
QMessageBox.information(self, "Abgeschlossen", meldung)
# *****************************************************************************
# Main
# *****************************************************************************
def main():
app = QApplication(sys.argv)
fenster = HauptFenster()
fenster.show()
sys.exit(app.exec())
if __name__ == "__main__":
main()
🐍 Skript herunterladen (.py)