shcshc
Goto Top

CMD und die Normal- bzw. Sommerzeit

Hallo,

ich habe für mein Problem schon einige Zeit nach einer Lösung gesucht, aber noch nicht den richtigen Hinweis gefunden. Daher hoffe ich, dass mich hier noch jemand in die richtige Richtung "schubsen" kann.

Aktion
Ich sichere verschiedene Windows-PCs u.a. 1x im Monat als komplettes Image mit TrueImageHome. Zusätzlich kopiere ich diese monatlichen Backups auf eine zweite Festplatte und benenne sie dabei um, da ich dort weitere Auswahl-Operationen anhand des Dateinamens vollziehe. Das Ganze erledige ich mit einer CMD-Batch, da ich mich (leider) mit PowerShell noch nicht so richtig auskenne. Hier fehlt mir die Zeit für ein intensives Studium der Befehle.
Ich lese das Erstelldatum/Uhrzeit aus der Datei aus wenn diese Datei noch nicht am Ziel existiert, kopiere ich sie und benenne sie mit Datum/Uhrzeit im Dateinamen um.

Problem
Bekannterweise interpretiert CMD die Normal/Sommerzeit anders als Powershell und der Windows-Explorer:
=> Das Erstell/Änderungsdatum einer im Sommer erstellten/geänderten Datei wird im Winter (Normalzeit) eine Stunde eher angezeigt
=> PowerShell wiederum zeigt wie der Explorer jeweils die gleiche Uhrzeit zur Normalzeit und zur Sommerzeit an.

Wenn ich nun eine Datei, die im September erstellt wurde im September umbenenne erhalte ich:
2021-09-01_10-00_abc

Wenn ich die gleiche Datei dann noch einmal im November prüfe erhalte ich aber
2021-09-01_09-00_abc

Und wenn dann geprüft wird, ob die Datei schon im Ziel existiert, wird sie natürlich zusätzlich kopiert, da die Dateinamen unterschiedlich sind.

Status
So weit ich mich eingelesen habe, ist das ein Problem von CMD und ich grübele, wie ich das Problem umgehen könnte. Vermutlich muss ich die Sache anders angehen, um nicht auf die Eigenheit von CMD zu stoßen.

a) Wenn ich bei meinem Ansatz bleibe, müsste ich fortwährend prüfen, ob wir uns aktuell in der Normal/Sommerzeit befinden und wann die zu prüfende Datei erstellt wurde, um dann entsprechend die Uhrzeit zu korrigieren. Das ist machbar, aber auch mit viel Aufwand/Hirnschmalz verbunden.

b) Mein Backup-Programm kann Datum und Uhrzeit nicht (mehr) sinnvoll in den Dateinamen schreiben

c) Direkt nach dem Backup kann ich die Datei nicht umenennen, da dann das Backup-Programm durcheinander kommt und die Datei nicht wiederfindet. Daher mache ich das erst bei der Kopie auf ein weiteres Backupmedium


Das ist mein Codeschnipsel, der mein Problem verursacht:
FOR /F "TOKENS=1,2,4 Delims= " %%a IN ('DIR /A-D /O-D /T:C %Backup_Quelle% ^| FINDSTR "Monat"') DO (  
	SET Jahr=%%a
	SET Zeit=%%b
	SETLOCAL EnableDelayedExpansion
	SET TIH-Datei=!Jahr:~-4!-!Jahr:~-7,2!-!Jahr:~-10,2!_!Zeit:~0,2!-!Zeit:~3,2!_%%c
	IF NOT EXIST %Backup_Ziel%\!TIH-Datei! (
		ECHO.
		ECHO ... %%c ...
		ECHO. & ECHO.
		ECHO - !TIH-Datei! >> %Temp1_SortBackups%
		ROBOCOPY /NDL /NFL /MIR /FFT /DST %Backup_Quelle%\ %Backup_Ziel%\ %%c
		REN %Backup_Ziel%\%%c !TIH-Datei!
		ENDLOCAL)
	)

Ich freue mich auf Ideen und Hinweise, wie ich das Ganze anders angehen könnte.


Vielen Dank,
SHC

Content-ID: 1477464365

Url: https://administrator.de/contentid/1477464365

Ausgedruckt am: 23.11.2024 um 12:11 Uhr

Tezzla
Tezzla 06.11.2021 aktualisiert um 20:24:24 Uhr
Goto Top
Moin,

ich würde da einen anderen Ansatz empfehlen: Prüfe nach File Hashes, ob dieser bereits in deinem Archiv existiert. Falls nicht, kopieren.
Der Dateiname ist dabei auch nicht relevant, sodass du das Benennungsproblem vollständig außen vor lassen kannst und die Dateien heißen können wie sie wollen.

Da würde ich aber tatsächlich zu Powershell raten, das geht damit deutlich einfacher.

So entgeht man auch dem Problem, sofern ein Kopiervorgang mal in die Hose gegangen ist. Dann stimmen die Hashes nicht und es wird neu kopiert.

Vg
shcshc
shcshc 07.11.2021 um 13:04:22 Uhr
Goto Top
Hallo Tezzla,

das ist eine guter Ansatz, der in der Tat mehrere Fliegen mit einer Klappe schlagen würde.

Ich habe das heute morgen mal getestet mit

certutil -hashfile %File1% MD5

Das funktioniert grundsätzlich prima (auch in CMD), allerdings sind Quelle/Ziel die limitierenden Faktoren, bzw. die Größe der Dateien. Da es sich um vollständige Images handelt, sind diese um 50Gbyte groß. Die Quelle liegt auf einem NAS, das Ziel auf einem USB-Laufwerk.

Auf dem NAS haben sich dadurch etwa 20min. für einen Hash ergeben, auf dem USB-Laufwerk etwa 5min.
D.h. in der Praxis müsste ich die Hash-Werte auf jeden Fall zwischenspeichern oder ein Tool wie TurboSFV (https://turbosfv.com/) verwenden, welches ich eh lizensiert habe. Dieses speichert per GUI oder CMD Hash-Werte von einzelnen Dateien oder Verzeichnissen in Textdateien. Die könnte ich dann auslesen und vergleichen.

Einziger Haken:
=> Mal angenommen die Datei 2021-07-01_10-00 ist unvollständig kopiert worden. Das bemerke ich über den falschen Hash-Wert. Dann würde das Script die Datei nochmal kopieren, weil auch der Dateinamenvergleich fehlschlägt (zur Normalzeit wäre das ja 2021-07-01_09-00). Somit hätte ich dann im Ergebnis wieder zwei Dateien auf dem USB-Laufwerk und müsste händisch heraus finden, woran es liegt.

Ich grübel da noch ein wenig weiter..... face-wink
rubberman
rubberman 07.11.2021 um 21:12:11 Uhr
Goto Top
Zitat von @shcshc:
da ich mich (leider) mit PowerShell noch nicht so richtig auskenne
Ich auch nicht.

Bekannterweise interpretiert CMD die Normal/Sommerzeit anders als Powershell und der Windows-Explorer
Zwei Minuten Suchmaschine hilft. Wenn's nur um Erstellungsdatum und Dateiname geht, lässt sich auch ein PowerShell Aufruf in einen Batchcode packen, wenn du damit besser zurecht kommst.
for /f "tokens=1*" %%i in (  
  'powershell -nop -ep Bypass -c "gci '%Backup_Quelle%' -filter '*Monat*' -file|sort CreationTime -descending|foreach{$_.CreationTime.ToString('yyyy-MM-dd_HH-mm_ ')+$_.Name}"'  
) do (
  echo %%i
  echo "%%j"  
  echo ~~~~~
)

Steffen
miniversum
miniversum 08.11.2021 um 13:35:14 Uhr
Goto Top
Hallo,

mach das umbenennen zuerst direkt auf dem System auf dem du die Datei erzeugst.
Also Backup erzeugeund danach die Backup Datei umbenennen mit Datum (hier kannst Du dann auch direkt die Systemvariabeln verwenden).
Die Backupdatei dann kopieren und bereits existierende (gleicher Dateiname) überspringen. Das geht ja beim Kopierbefehl direkt per Parameter.

Ich dachte allerdings auch das TrueImageHome den Namen flexibel direkt mit dem aktuellen Datum (als Variable im Namen) erzeugen kann...

Gruß ...
shcshc
shcshc 08.11.2021 um 20:08:47 Uhr
Goto Top
@rubberman:
Vielen Dank für diesen tollen Tipp! Ich werde mir das in Ruhe ansehen und versuche zu verstehen, was der Befehl genau macht. Ehrlicherweise wäre ich da auch mit zwei Stunden Suchmaschine nie drauf gekommen. Daher 1000 Dank!

@miniversum:
Danke für Deine Gedanken! Leider versteckt TIH seit 2015 die Möglichkeit per Variable auch das Datum einzubinden. Seit 2019 ist es sogar schlicht nicht mehr möglich - selbst wenn man die Profildatei händisch anpasst.
Daher möchte ich die Sicherungsdatei auch nicht sofort umbenennen, da dann TIH die Daten nicht mehr erkennt und nicht mehr selbstständig aufräumen kann.

Vielen Dank für Eure Hinweise! Ich werde in ein paar Tagen berichten, wie ich vorgegangen bin.
SHC
rubberman
rubberman 08.11.2021 aktualisiert um 21:12:57 Uhr
Goto Top
Ich werde mir das in Ruhe ansehen und versuche zu verstehen, was der Befehl genau macht.

Ist genau das was im Kopf deiner FOR Schleife jetzt auch schon passiert, nur dass du deinen Zeitstempel schon formatiert bekommst.

gci '%Backup_Quelle%' -filter '*Monat*' -file
Get-ChildItem (alias gci) sucht im Pfad %Backup_Quelle%. Da das ganze in einem Batchcode ausgeführt wird, ersetzt die CMD die Variable durch den Wert bevor PowerShell aufgerufen wird.
Gefiltert wird nach Namen die Monat enthalten, die Sternchen sind Wildcards für "irgendwas oder nichts". Ist quasi das was dein nachgeschalteter FINDSTR Aufruf macht.
Gesucht wird nur nach Dateien, nicht nach Verzeichnissen. Entspricht deiner Option /A-D für DIR.

|sort CreationTime -descending
Die gefundenen Dateiobjekte werden per Pipe an Sort-Object (alias sort) weitergegeben, die diese nach ihrer CreationTime Eigenschaft sortiert, und zwar absteigend. Entspricht deinen Optionen /T:C und /O-D für DIR.

|foreach{$_.CreationTime.ToString('yyyy-MM-dd_HH-mm_ ')+$_.Name}
Die sortierten Dateiobjekte werden per Pipe an ForEach-Object (alias foreach) weitergereicht. Die geschweiften Klammern sind dabei wie der Rumpf einer Schleife zu betrachten, bei der $_ in jedem Schleifendurchlauf je ein Dateiobjekt zugewiesen wird. Zuerst holen wir uns die CreationTime Eigenschaft des Objekts und formatieren sie in einen String, der auch gleich so aussieht wie du ihn für die neuen Dateinamen brauchst. Das nachgestellte Leerzeichen ist der Delimiter in der Batch FOR Schleife um den Inhalt von %%i und %%j voneinander zu trennen. Das + ist hier der Operator für Stringverkettung. Angehängt wird die Name Eigenschaft des Objekts. Das ganze ergib also einen String à la
2021-11-08_21-05_ Datei mit Monat im Name.ext, der allein steht (nicht einer Variablen zugewiesen oder per Pipe weitergeleitet wird). Somit wird er implizit als neue Zeile in die Ausgabe geschrieben.

Das Ganze wird per PowerShell ausgeführt und die Ausgabe wird durch die Batch FOR Schleife zeilenweise gelesen. Das "tokens=1*" sorgt dafür, dass der erste durch Leerzeichen getrennte Teilstring in %%i landet, der ganze Rest (egal ob weitere Leerzeichen vorhanden sind) in %%j.

That's it.

Steffen
shcshc
shcshc 09.11.2021 um 19:28:19 Uhr
Goto Top
@steffen

Vielen herzlichen Dank für die ausführliche Erläuterung. Das ist wirklich toll und weiß ich sehr zu schätzen!

Ich werde das einbauen und mich danach wieder melden!


1000 Dank,
SHC
shcshc
shcshc 15.11.2021 um 22:13:29 Uhr
Goto Top
Hallo Steffen,

ich möchte mich noch einmal herzlich für Deine Hilfe bedanken. Das hat alles funktioniert und läuft reibungslos. Auch die Befehle habe ich dank Deiner Erklärung verstanden und werde versuchen meine Powershell-Kenntnisse demnächst auszuweiten.

Viele Grüße,
SHC