Sicherungs cmd mit Archivbitabfrage
Hallo zusammen
Ich habe mich hier im Forum schon ein wenig umgesehen gehabt komm aber leider an 2 Punkten nicht weiter.
Mein Problem :
Ich benötige eine CMD, die mir alle Datein aus einer Verzeichnissstruktur ausliest.
hierbei sollen aber nur neue bzw bearbeitette Dateien Berücksichtigt werden. (mom summe Dateien ca 6500 Täglicher zuwachs ca 40)
das währe ja erstmal kein Problem ABER
bereits existierende Dateien Dürfen nicht überschreiben werden.
sollte also einer in einem Dokument bearbeitet haben muss diese in ein neues Verzeichniss gespeichert werden.
so und genau da liegen meine Probleme
Filtern nach Attrib A
Abfrage ob Attrib Pfad\Datei == A .....
das bekomm ich patu nicht hin
und wo ich auch verzweifel ist
Ich Frage die Dateien mit einer For Schleife ab
das Verzeichniss ist dann z.B. Z:\dasi\PC1\
Das soll jetzt mit dem Verzeichniss \\10.0.105.94\Daten\PC1\
Verglichen werden.
Wie Trenn ich vernünfig die Variable mit z.B. Z:\dasi\PC1\test.doc in PC1\test.doc
Für jede Hilfe bin ich Dankbar
Ich habe mich hier im Forum schon ein wenig umgesehen gehabt komm aber leider an 2 Punkten nicht weiter.
Mein Problem :
Ich benötige eine CMD, die mir alle Datein aus einer Verzeichnissstruktur ausliest.
hierbei sollen aber nur neue bzw bearbeitette Dateien Berücksichtigt werden. (mom summe Dateien ca 6500 Täglicher zuwachs ca 40)
das währe ja erstmal kein Problem ABER
bereits existierende Dateien Dürfen nicht überschreiben werden.
sollte also einer in einem Dokument bearbeitet haben muss diese in ein neues Verzeichniss gespeichert werden.
so und genau da liegen meine Probleme
Filtern nach Attrib A
Abfrage ob Attrib Pfad\Datei == A .....
das bekomm ich patu nicht hin
und wo ich auch verzweifel ist
Ich Frage die Dateien mit einer For Schleife ab
das Verzeichniss ist dann z.B. Z:\dasi\PC1\
Das soll jetzt mit dem Verzeichniss \\10.0.105.94\Daten\PC1\
Verglichen werden.
Wie Trenn ich vernünfig die Variable mit z.B. Z:\dasi\PC1\test.doc in PC1\test.doc
Für jede Hilfe bin ich Dankbar
Bitte markiere auch die Kommentare, die zur Lösung des Beitrags beigetragen haben
Content-ID: 167460
Url: https://administrator.de/forum/sicherungs-cmd-mit-archivbitabfrage-167460.html
Ausgedruckt am: 11.04.2025 um 10:04 Uhr
24 Kommentare
Neuester Kommentar
Dateien mit aktivem "Archiv" Attribut lassen sich mit
filtern. Wenn du das ganze für alle Unterverzeichnisse brauchst füge den Parameter /S hinzu.
für das trennen der Variablen kannst du die Stringmanipulationen benutzen z.B. extrahiert folgender Befehl aus "Z:\dasi\PC1\test.doc" die Zeichenfolge "PC1\test.doc"
Sie übernimmt alles ab dem 8 Zeichen des Strings. Die 250 steht für die Anzahl der Zeichen die max. übernommen werden sollen
Wie man die Befehle benutzt steht hier: http://www.dostips.com/DtTipsStringManipulation.php
dir /AA /B
für das trennen der Variablen kannst du die Stringmanipulationen benutzen z.B. extrahiert folgender Befehl aus "Z:\dasi\PC1\test.doc" die Zeichenfolge "PC1\test.doc"
echo %VARIABLE:~8,250%
Wie man die Befehle benutzt steht hier: http://www.dostips.com/DtTipsStringManipulation.php
Hallo dihe85,
um die Auftrennung allgemeiner und nicht auf feste Offsets festzulegen, gibt es auch noch folgende Möglichkeit:
Ausgabe:
Siehe auch
Gruß
Friemler
um die Auftrennung allgemeiner und nicht auf feste Offsets festzulegen, gibt es auch noch folgende Möglichkeit:
set "Variable=Z:\dasi\PC1\test.doc"
::
::
::
for /f "delims=" %%s in ("%Variable%") do echo %%~ds
for /f "delims=" %%s in ("%Variable%") do echo %%~dps
for /f "delims=" %%s in ("%Variable%") do echo %%~ns
for /f "delims=" %%s in ("%Variable%") do echo %%~xs
for /f "delims=" %%s in ("%Variable%") do echo %%~nxs
Ausgabe:
Z:
Z:\dasi\PC1\
test
.doc
test.doc
Siehe auch
FOR /?
oder mein Tutorial zur FOR-Schleife.Gruß
Friemler
Hallo dihe85,
An die Laufvariable
Das schon oben erwähnte Tutorial zur FOR-Schleife wird Dir weiterhelfen.
Gruß
Friemler
mir ist nur nicht Klar wie ich mit dir /AA/B/S weiterarbeiten soll.
Dann nimmfor /f "delims=" %%f in ('dir /s /b /a:a "Pfad\Dateimaske" 2^>NUL') do ...
%%f
werden dann nacheinander alle Dateinamen inkl. Pfad zugewiesen, bei denen das Archivbit gesetzt ist.Da kommt dann aber als Ergebniss nur ~8,250 raus
Dein Stichwort heißt "verzögerte Variablenerweiterung".ein weiteres Problem ist das ich das so warscheinlich nicht machen kann, da die Verzeichnisse unterschiedliche Zeichenlängen haben
Siehe mein letztes Posting.Das schon oben erwähnte Tutorial zur FOR-Schleife wird Dir weiterhelfen.
Gruß
Friemler
Hallo Dirk,
nochmal auf die sanfte Art:
Du sagst, Du hast in das Tut schon reingeschaut. Deine Frage "Was ist
innerhalb einer
Ich wünsche Dir Geduld und Erfolg
Friemler
nochmal auf die sanfte Art:
FOR /F
ist ein ziemlich komplexer Befehl. All die Dinge, die damit zusammenhängen, jedesmal zu erklären, wenn ein Batchanfänger wie Du Probleme damit hat, ist einfach zu viel Aufwand. Deshalb habe ich das Tutorial geschrieben. Ich weiß, es ist sehr lang und man möchte lieber einen schnellen Erfolg beim Scripten als ellenlange Tuts lesen. Aber ich fürchte, da kommst Du nicht drumherum. Vom Lesen alleine wird man auch nicht schlau, man muss die vielen Kleinigkeiten auch in kleinen, auf ein bestimmtes Feature abgestimmten Übungs-Scripts erforschen. Vorselektieren der Themen in Bezug auf das, was man gerade wissen möchte, verkürzt die Zeit bis Dein Programm läuft.Du sagst, Du hast in das Tut schon reingeschaut. Deine Frage "Was ist
%%~dps
?" spricht dagegen. Ebensoset te=%%f
echo %te%
FOR
-Schleife.Ich wünsche Dir Geduld und Erfolg
Friemler
Hallo @all!
Noch eine Ergänzung: Eigentilch sollte es ja hier darum gehen, einen relativen Pfad (bezogen auf einen Basis-Ordner) zu ermitteln - dann würde ich das schematisch eher so anlegen (bitte den "\" am Ende des Basispfades beachten):
Grüße
bastla
Noch eine Ergänzung: Eigentilch sollte es ja hier darum gehen, einen relativen Pfad (bezogen auf einen Basis-Ordner) zu ermitteln - dann würde ich das schematisch eher so anlegen (bitte den "\" am Ende des Basispfades beachten):
@echo off & setlocal
set "Basis=Z:\dasi\"
set "Datei=Z:\dasi\PC1\test.doc"
call set "PfadRelativ=%%Datei:*%Basis%=%%"
echo %PfadRelativ%
bastla
Hallo Dirk,
nachdem ich mir nochmal Dein Eröffnungsposting gründlicher durchgelesen habe (auch die Überschrift
), stellt sich mir die Frage, ob Du nicht besser
Da Dein Ziel eine Netzwerkfreigabe ist, wäre auch über die Verwendung von
Gruß
Friemler
nachdem ich mir nochmal Dein Eröffnungsposting gründlicher durchgelesen habe (auch die Überschrift
XCOPY
mit der Option /M
verwenden solltest. Durch diese Option werden nur Dateien mit gesetztem Archivattribut kopiert und das Archivbit nach dem kopieren gelöscht. Das würde Dir das Schreiben von Code zur Auswahl der zu kopierenden Dateien und das generieren von Zielpfaden ersparen. Als Zielverzeichnis kannst Du bei jedem Kopiervorgang ein anderes angeben, was z.B. einen Datumsstempel im Namen enthält. Die Verzeichnisstruktur der Quelle bleibt dabei erhalten.Da Dein Ziel eine Netzwerkfreigabe ist, wäre auch über die Verwendung von
ROBOCOPY
nachzudenken, was dafür besser geeignet wäre. Auch ROBOCOPY
hat das Feature mit dem selektiven kopieren von Dateien nach Archivattribut und anschließendem zurücksetzen.Gruß
Friemler
Hallo Dirk,
wenn ich Dich richtig verstehe, willst Du im Ziel des Backups ein Verzeichnis, was nach jedem Backup eine exakte Kopie des Quellverzeichnisses darstellt. Um zu verhindern, dass seit dem letzten Backup geänderte Dateien ihre alten Versionen im Backupverzeichnis überschreiben, sollen die alten Versionen vor dem überschreiben in einem anderen Verzeichnis gesichert werden. Soweit korrekt?
Zufälligerweise verwende ich privat die selbe Strategie. Ich poste deshalb einfach mal mein privates Backupscript, basierend auf
Damit es funktioniert, müssen Quell- und Ziellaufwerk verschieden sein! Sollte bei Backups aber sowieso der Fall sein.
Vorteil der Methode ist, dass auch das Verschieben eines kompletten Verzeichnisses als Änderung bemerkt wird. Über die Abfrage des Archivbits wäre das nicht so.
Hier dann noch der VBS-Code für die Dialogboxen:
Gruß
Friemler
wenn ich Dich richtig verstehe, willst Du im Ziel des Backups ein Verzeichnis, was nach jedem Backup eine exakte Kopie des Quellverzeichnisses darstellt. Um zu verhindern, dass seit dem letzten Backup geänderte Dateien ihre alten Versionen im Backupverzeichnis überschreiben, sollen die alten Versionen vor dem überschreiben in einem anderen Verzeichnis gesichert werden. Soweit korrekt?
Zufälligerweise verwende ich privat die selbe Strategie. Ich poste deshalb einfach mal mein privates Backupscript, basierend auf
ROBOCOPY
. Falls Du Vista oder Windows 7 einsetzt, hast Du es schon an Bord. Für XP musst Du es Dir hier herunterladen. Auf den Link "UtilitySpotlight2006_11.exe" klicken. Die Datei enthält auch ein Word-Dokument mit einer ausführlichen Dokumentation.Damit es funktioniert, müssen Quell- und Ziellaufwerk verschieden sein! Sollte bei Backups aber sowieso der Fall sein.
Vorteil der Methode ist, dass auch das Verschieben eines kompletten Verzeichnisses als Änderung bemerkt wird. Über die Abfrage des Archivbits wäre das nicht so.
@echo off
setlocal
::Script zur Synchronisierung mehrerer Quellverzeichnisse mit einem Ziel-
::verzeichnis.
::Vor der Synchronisierung wird geprüft, ob die Datenträgerbezeichnung korrekt ist.
::So wird bei USB-Datenträgern als Ziellaufwerk sichergestellt, daß kein anderes
::USB-Laufwerk den gewählten Laufwerksbuchstaben zugewiesen bekommen hat.
::Dateien, die beim Synchronisieren gelöscht oder überschrieben werden, werden
::vorher in ein Sicherungsverzeichnis verschoben. So kann man immer wieder zu
::einem alten Backupstand zurückkehren.
::Bei allen Aktionen wird ein Eintrag in eine LogDatei erstellt, die nach Abschluß
::auf Fehlermeldungen untersucht wird. Falls Fehler aufgetreten sind, wird eine
::Meldung ausgegeben.
::Bei fehlerfreiem Ablauf gibt das Script in ERRORLEVEL 0 zurück, bei Fehlern
::ist ERRORLEVEL 1 und bei Benutzerabbruch 2.
::Quellverzeichnisse
::Wenn die Pfade Leerzeichen enthalten,
::MÜSSEN sie in Anführungszeichen eingeschlossen werden!!
set Source="D:\Archiv" "D:\ct" "D:\Script" "D:\Neu-Installation"
set Source=%Source% "D:\Office-Dokumente" "D:\Sicherungen"
::Ziellaufwerk und seine Datenträgerbezeichnung
::Beides OHNE Anführungszeichen!!
set DestDrv=P:
set DestDrvName=EXTERN
::Zielverzeichnis,
::OHNE Anführungszeichen!!
set Dest=%DestDrv%\D - DATEN
::Zielverzeichnis für alte Versionen
set oldVersions=%Dest%\Alte Versionen
::Zeitstempel
set Now=%DATE:~6,4%-%DATE:~3,2%-%DATE:~0,2%_%TIME:~0,2%-%TIME:~3,2%-%TIME:~6,2%
::Pfad und Name der Log-Datei
set Logfile=%Dest%\Backup-Logs\%Now%.log
::Text der Dialogbox, die angezeigt wird,
::wenn das richtige Ziellaufwerk nicht vorhanden ist.
::MIT Anführungszeichen!!
set WrongHDMsg="Falsche Festplatte angeschlossen!"
::Text der Dialogbox, die angezeigt wird, wenn während
::der Synchronisierung ein Fehler aufgetreten ist.
::MIT Anführungszeichen!!
set ErrMsg="Während der Synchronisierung ist ein Fehler aufgetreten!|Die Log-Datei enthält weitere Informationen."
::Prüfen, ob das richtige Ziellaufwerk angeschlossen ist
for /f "tokens=6" %%I in ('vol %DestDrv%') do (
set Volume=%%I
)
if "%Volume%" equ "%DestDrvName%" goto :DoBackup
cscript /nologo "%~dp0MsgBox.vbs" %WrongHDMsg% OK "%~n0" Critical
exit /B 1
:DoBackup
::Synchronisierung ausführen
::Header schreiben
> "%Logfile%" echo Daten-Backup %Now%
>>"%Logfile%" echo ================================
>>"%Logfile%" echo.
>>"%Logfile%" echo.
::Die Dateien ermitteln, die bei einer Synchronisierung gelöscht
::oder überschrieben werden. Im Unterprogramm werden diese Dateien
::in einen Sicherungsordner verschoben und entsprechende Einträge
::ins Log-File geschrieben.
for %%S in (%Source%) do (
for /f "tokens=1,2*" %%F in ('call "%~dp0RoboCopy" "%%~S" "%Dest%\%%~nS" *.* /XD .svn /ZB /MIR /COPY:DAT /DCOPY:T /IT /FP /NDL /NP /L /NJH /NJS /NS ^| findstr /r /c:"\<\*EXTRA File\>" /c:"\<Newer\>" /c:"\<Older\>" /c:"\<Changed\>" /c:"\<Tweaked\>"') do (
if "%%F %%G" equ "*EXTRA File" (
set "oldFile=%%H"
call :SaveOldFile "NUR IM ZIEL"
) else if "%%F" equ "Newer" (
set "oldFile=%%G %%H"
call :SaveOldFile "NEUER"
) else if "%%F" equ "Older" (
set "oldFile=%%G %%H"
call :SaveOldFile "AELTER"
) else if "%%F" equ "Changed" (
set "oldFile=%%G %%H"
call :SaveOldFile "VERAENDERT"
) else if "%%F" equ "Tweaked" (
set "oldFile=%%G %%H"
call :SaveOldFile "ATTRIBUTE GEAENDERT"
)
)
)
::Die Synchronisierung ausführen. Es wird ein exaktes Abbild der Quelldateien
::und -verzeichnisse erstellt (inkl. Zeitstempel und Dateiattribute).
for %%S in (%Source%) do (
>>"%Logfile%" "%~d0%~p0RoboCopy" "%%~S" "%Dest%\%%~nS" *.* /XD .svn /ZB /MIR /COPY:DAT /DCOPY:T /IT /FP /NDL /NP 2>>&1
>>"%Logfile%" echo.
>>"%Logfile%" echo.
>>"%Logfile%" echo.
)
::In der Log-Datei nach Fehlermeldungen suchen
::Falls Fehlermeldungen vorhanden sind, Meldung ausgeben,
findstr "\<ERROR\>" "%Logfile%" > NUL
if %ERRORLEVEL% equ 0 (
cscript /nologo "%~dp0MsgBox.vbs" %ErrMsg% OK "%~n0" Critical
exit /b 1
)
::Fehlerfreier Ablauf -> Rückgabewert 0
exit /b 0
:SaveOldFile
setlocal
::Leerzeichen am Ende des Dateinamens abschneiden.
::Kann durch die FOR-Schleife im Hauptprogramm entstehen
if "%oldFile:~-1%" equ " " set "oldFile=%oldFile:~0,-1%"
::Wenn der Dateipfad auf das Ziellaufwerk verweist,
::wurde die Datei in der Quelle gelöscht
if /i "%oldFile:~0,2%" equ "%DestDrv%" goto :SaveDeletedFile
::Für in der Quelle geänderte Dateien den
::Dateipfad auf ein einheitliches Format bringen
:SaveUpdatedFile
set "oldFile=%Dest%%oldFile:~2%"
::Pfad zum Backupverzeichnis entfernen und durch den
::Pfad zum Verzeichnis für alte Versionen ersetzen
:SaveDeletedFile
call set "newPath=%%oldFile:*%Dest%=%%"
set "newPath=%oldVersions%\%Now%%newPath%"
::Eintrag in die Logdatei schreiben
(echo %~1
set /p "=%oldFile%" <NUL & echo.
echo verschoben nach
set /p "=%newPath%" <NUL & echo.) >>"%Logfile%"
::Im Verzeichnis für alte Versionen die Verzeichnisstruktur anlegen,
::unter der die Datei im Quell- und im Backupverzeichnis abgelegt ist
::und die Datei verschieben
for /f "delims=" %%P in ("%newPath%") do (mkdir "%%~dpP" 2>NUL)
move "%oldFile%" "%newPath%" 2>>"%Logfile%"
::Zwei Leerzeilen in die Logdatei schreiben
(echo.&echo.)>>"%Logfile%"
endlocal
exit /b
Hier dann noch der VBS-Code für die Dialogboxen:
Dim listArgs, strMessage, strButtons, strTitle, strIcon, strDefaultButton
Dim intButtons, intResult
Set listArgs=WScript.Arguments
If listArgs.Count >= 1 Then
strMessage = listArgs(0)
If listArgs.Count >= 2 Then strButtons = UCase(listArgs(1))
If listArgs.Count >= 3 Then strTitle = listArgs(2)
If listArgs.Count >= 4 Then strIcon = UCase(listArgs(3))
If listArgs.Count >= 5 Then strDefaultButton = listArgs(4)
intButtons = 0
If strButtons = "OKCANCEL" Then intButtons = intButtons + vbOKCancel
If strButtons = "ABORTRETRYIGNORE" Then intButtons = intButtons + vbAbortRetryIgnore
If strButtons = "YESNOCANCEL" Then intButtons = intButtons + vbYesNoCancel
If strButtons = "YESNO" Then intButtons = intButtons + vbYesNo
If strButtons = "RETRYCANCEL" Then intButtons = intButtons + vbRetryCancel
If strIcon = "CRITICAL" Then intButtons = intButtons + vbCritical
If strIcon = "QUESTION" Then intButtons = intButtons + vbQuestion
If strIcon = "EXCLAMATION" Then intButtons = intButtons + vbExclamation
If strIcon = "INFORMATION" Then intButtons = intButtons + vbInformation
If strDefaultButton = "2" Then intButtons = intButtons + vbDefaultButton2
If strDefaultButton = "3" Then intButtons = intButtons + vbDefaultButton3
strMessage = Replace(strMessage, "|", vbCrLf)
intResult = Msgbox(strMessage, intButtons, strTitle)
WScript.Quit intResult
Else
WScript.Quit 0
End If
Gruß
Friemler
Hallo dihe85!
Kurz zu "
Konkret wird so aus zB
mit einem Basispfad
eben der relative Pfad
Grüße
bastla
Kurz zu "
xcopy
": Wenn Du das Ziel mit abschließendem "\" angibst, zeigst Du an, dass damit ein Verzeichnis gemeint ist, und die entsprechende Frage ist hinfällig; soll das Ziel eine Datei sein, setz noch einen "*" an das Ende ...wofür stehen diese Steuerzeichen und wieso nimmt er das von "links" weg ???
"Steuerzeichen" gibt es eigentlich nicht - es wird nur (wegen "delayedExpansion
") die erst in der Schleife erstellte / geänderte Variable "%Datei%" jetzt eben "!Datei!" geschrieben - der Rest ist "normale" Stringersetzung (durch nix, wodurch der Basispfad wegfällt) , wie in "set /?
" nachzulesen: %PATH:str1=str2%
Dies erweitert die PATH-Umgebungsvariable, wobei jede Instanz von "str1" im
erweiterten Ergebnis mit "str2" ersetzt wird. "str2" kann die leere
Zeichenfolge sein, um alle Instanzen von "str1" aus der erweiterten Ausgabe zu
löschen. Wenn "str1" mit einem Sternchen beginnt, steht "str1" für alles
zwischen dem Anfang der erweiterten Ausgabe bis zum ersten Auftreten des
übrigen Abschnitts von "str1".
Dies erweitert die PATH-Umgebungsvariable, wobei jede Instanz von "str1" im
erweiterten Ergebnis mit "str2" ersetzt wird. "str2" kann die leere
Zeichenfolge sein, um alle Instanzen von "str1" aus der erweiterten Ausgabe zu
löschen. Wenn "str1" mit einem Sternchen beginnt, steht "str1" für alles
zwischen dem Anfang der erweiterten Ausgabe bis zum ersten Auftreten des
übrigen Abschnitts von "str1".
Konkret wird so aus zB
Z:\Dasi\CA\AAS1\Eine Datei
Z:\Dasi\
CA\AAS1\Eine Datei
bastla