84409
06.07.2011, aktualisiert am 18.10.2012
9965
28
0
Zippen mittels VBS
Hallo zusammen, ich habe mal wieder eine Aufgabe, die ich ohne Eure Hilfe mit VB Script nicht gelöst bekomme:
Dateien (unterschiedliche Dateitypen) aus einem Ordner deren "LastModified" Datum eine gewisse Zeit zurück liegt (beispielsweise 3 Monate)
sollen gezippt werden. Diese ZIP Datei soll ebenfalls in einem anderen Ordner liegen als die Dateinen.
So weit bin ich schon mit zusammen geklauten VBS Schnipseln gekommen:
Dateien (unterschiedliche Dateitypen) aus einem Ordner deren "LastModified" Datum eine gewisse Zeit zurück liegt (beispielsweise 3 Monate)
sollen gezippt werden. Diese ZIP Datei soll ebenfalls in einem anderen Ordner liegen als die Dateinen.
So weit bin ich schon mit zusammen geklauten VBS Schnipseln gekommen:
Option Explicit
Dim myFolder, myZipFile, arrResult
myFolder = "C:\Test\"
myZipFile = ("\\server\ARCHIV\" & (Date()&".zip"))
arrResult = ZipFolder( myFolder, myZipFile )
'If arrResult(0) = 0 Then
' If arrResult(1) = 1 Then
' WScript.Echo "Done; 1 empty subfolder was skipped."
' Else
' WScript.Echo "Done; " & arrResult(1) & " empty subfolders were skipped."
' End If
'Else
' WScript.Echo "ERROR " & Join( arrResult, vbCrLf )
'End If
Function ZipFolder( myFolder, myZipFile )
Dim intSkipped, intSrcItems
Dim objApp, objFolder, objFSO, objItem, objTxt, FileObj, CheckVerzeichnis, altesDatum
Dim strSkipped
Const ForWriting = 2
intSkipped = 0
' Use custom error handling
On Error Resume Next
' Create an empty ZIP file
Set objFSO = CreateObject( "Scripting.FileSystemObject" )
Set objTxt = objFSO.OpenTextFile( myZipFile, ForWriting, True )
objTxt.Write Chr(80) & Chr(75) & Chr(5) & Chr(6) & String(18, Chr(0) ) '"PK" & Chr(5) & Chr(6) & String( 18, Chr(0) )
objTxt.Close
Set objTxt = Nothing
' Abort on errors
If Err Then
ZipFolder = Array( Err.Number, Err.Source, Err.Description )
Err.Clear
On Error Goto 0
Exit Function
End If
' Create a Shell object
Set objApp = CreateObject( "Shell.Application" )
Set FileObj = CreateObject("Scripting.FileSystemObject")
Set CheckVerzeichnis = FileObj.GetFolder( myFolder )
'Set FSO = CreateObject( "Scripting.FileSystemObject" )
'Set oZDatei = FSO.OpenTextFile(counterFile, 2, True)
' Copy the files to the compressed folder <- AB HIER WIRD DIE ZIP DATEI BEFÜLLT, DA MUSS MIT DEM DATUM GEARBEITET WERDEN, NUR WIE?
For Each objItem in objApp.NameSpace( myFolder ).Items
If objItem.IsFolder Then
' Check if the subfolder is empty, and if
' so, skip it to prevent an error message
Set objFolder = objFSO.GetFolder( objItem.Path )
If objFolder.Files.Count + objFolder.SubFolders.Count = 0 Then
intSkipped = intSkipped + 1
Else
objApp.NameSpace( myZipFile ).CopyHere objItem
WScript.Sleep 1000
End If
Else
For Each datei In CheckVerzeichnis.Files
'altesDatum = datei.DateCreated
MsgBox ("Datum: " & (datei.DateCreated))
Next
objApp.NameSpace( myZipFile ).CopyHere objItem
WScript.Sleep 1000
End If
Next
Set objFolder = Nothing
Set objFSO = Nothing
' Abort on errors
If Err Then
ZipFolder = Array( Err.Number, Err.Source, Err.Description )
Set objApp = Nothing
Err.Clear
On Error Goto 0
Exit Function
End If
' Keep script waiting until compression is done
intSrcItems = objApp.NameSpace( myFolder ).Items.Count
Do Until objApp.NameSpace( myZipFile ).Items.Count + intSkipped = intSrcItems
WScript.Sleep 1000
Loop
Set objApp = Nothing
' Abort on errors
If Err Then
ZipFolder = Array( Err.Number, Err.Source, Err.Description )
Err.Clear
On Error Goto 0
Exit Function
End If
' Restore default error handling
On Error Goto 0
' Return message if empty subfolders were skipped
If intSkipped = 0 Then
strSkipped = ""
Else
strSkipped = "skipped empty subfolders"
End If
' Return code 0 (no error occurred)
ZipFolder = Array( 0, intSkipped, strSkipped )
End Function
Bitte markiere auch die Kommentare, die zur Lösung des Beitrags beigetragen haben
Content-ID: 169246
Url: https://administrator.de/contentid/169246
Ausgedruckt am: 22.11.2024 um 04:11 Uhr
28 Kommentare
Neuester Kommentar
Hallo sascha123!
Gerade hinsichtilch des Debuggings ein Tipp vorweg: Verwende anstelle von "
Deine (nicht genannte) Fehlermeldung für die Zeile 11 sollte "Object doesn't support this property or method: 'objItem.DateLastModified'" sein - verwende (wie oben in Deinem Script in den Zeilen 72 - 75 bereits angedeutet) das entsprechende "FileSystemObjekt", also etwa
Da bei der Ausgabe ohnehin das Timestamp-Format (Datum + Uhrzeit) verwendet wird, ist die Konvertierung in einen String nicht erforderlich.
Um das Alter der Datei vergleichen zu können, solltest Du (einmal) vorweg mittels eines "
Grüße
bastla
Gerade hinsichtilch des Debuggings ein Tipp vorweg: Verwende anstelle von "
MsgBox
" die Ausgabe mit "WScript.Echo
" - wenn Du das Script mit "wscript.exe
" ausführen lässt, erhältst Du weiterhin eine MessageBox, aber beim Testen mit "cscript.exe
" werden die Ausgaben (ohne jede einzelne bestätigen zu müssen) in die Konsole geschrieben ...Deine (nicht genannte) Fehlermeldung für die Zeile 11 sollte "Object doesn't support this property or method: 'objItem.DateLastModified'" sein - verwende (wie oben in Deinem Script in den Zeilen 72 - 75 bereits angedeutet) das entsprechende "FileSystemObjekt", also etwa
Datum = objFSO.GetFile(objItem.Path).DateLastModified
Um das Alter der Datei vergleichen zu können, solltest Du (einmal) vorweg mittels eines "
DateAdd()
" die gewünschte Anzahl von Tagen / Monaten zurückrechnen und das Ergebnis mit dem ausgelesenen Datum vergleichen, also etwa:Alt = DateAdd("m", -3, Date)
...
If Datum < Alt Then 'alte Datei
...
Grüße
bastla
Hallo sascha123!
Mal abgesehen davon, dass Zeile 9 sich nicht auf eine Datei bezieht und daher
lauten müsste: Bei meinem Test macht das Script, was es soll ...
Noch zwei Anmerkungen:
Die Ermittlung von "Alt" würde ich, wie schon erwähnt, nur ein einziges Mal (und daher bereits vor der Schleife) durchführen.
Du brauchst nur ein einziges "FileSystemObject" zu erstellen (und das sinnvoller Weise auch gleich am Anfang des Scripts) - einmal "objFSO", dann wieder "FileObj" zu verwenden ist nicht zielführend ...
Grüße
bastla
Mal abgesehen davon, dass Zeile 9 sich nicht auf eine Datei bezieht und daher
Datum = objFSO.GetFolder(objItem.Path).DateLastModified
Alt ist das jetzige Datum MINUS 3 Monate ("m")???
Genau das.Noch zwei Anmerkungen:
Die Ermittlung von "Alt" würde ich, wie schon erwähnt, nur ein einziges Mal (und daher bereits vor der Schleife) durchführen.
Du brauchst nur ein einziges "FileSystemObject" zu erstellen (und das sinnvoller Weise auch gleich am Anfang des Scripts) - einmal "objFSO", dann wieder "FileObj" zu verwenden ist nicht zielführend ...
Grüße
bastla
Hallo sascha123!
wird gefragt, ob "Datum" früher als "Alt" (und damit die Datei älter als das Vergleichsdatum - was dem bekannten Phänomen "auf den ältesten Fotos sieht man am jüngsten aus" entspricht ) ist ...
Bei mir funktionier jedenfalls der folgende Schnipsel wunschgemäß:
Beim Testen starte ich aus einem CMD-Fenster mit
Grüße
bastla
Mir scheint es auch so, als hättest du das '<' Zeichen falscher herum angewendet?
Aufgrund der Tatsache, dass das Datum ja eigentlich ein Zahlenwert ist, hat ein früheres Datum einen niedrigeren Wert - wenn daher der Vergleich lautet:If Datum < Alt Then
Bei mir funktionier jedenfalls der folgende Schnipsel wunschgemäß:
myFolder ="D:\TEMP"
Set objApp = CreateObject( "Shell.Application" )
Set ObjFSO = CreateObject("Scripting.FileSystemObject")
Set CheckVerzeichnis = ObjFSO.GetFolder( myFolder )
Alt = DateAdd("m", -3, Date)
For Each objItem in objApp.NameSpace(myFolder).Items
If objItem.IsFolder Then
' Check if the subfolder is empty, and if
' so, skip it to prevent an error message
Set objFolder = objFSO.GetFolder( objItem.Path )
If objFolder.Files.Count + objFolder.SubFolders.Count = 0 Then
intSkipped = intSkipped + 1
Else
Datum = objFSO.GetFolder(objItem.Path).DateLastModified
'MsgBox ("Check U " & Datum) 'DateLastModified
If Datum < Alt Then 'alte Datei
'objApp.NameSpace( myZipFile ).CopyHere objItem
WScript.Echo "Alt U: " & Datum & " " & objItem.Name
'oZDatei.WriteLine "Test Unterverzeichnis"'(CInt(objFolder.Files.Count) + CInt(objFolder.SubFolders.Files.Count))
'oZDatei.Close
'WScript.Sleep 1000
Else
WScript.Echo "Neu U: " & Datum & " " & objItem.Name
End If
End If
Else
Datum = objFSO.GetFile(objItem.Path).DateLastModified
'MsgBox ("Check V " & Datum) 'DateLastModified
If Datum < Alt Then 'alte Datei
'objApp.NameSpace( myZipFile ).CopyHere objItem
WScript.Echo "Alt V: " & Datum & " " & objItem.Name
'oZDatei.WriteLine "Test Unterverzeichnis"'(CInt(objFolder.Files.Count) + CInt(objFolder.SubFolders.Files.Count))
'oZDatei.Close
'WScript.Sleep 1000
Else
WScript.Echo "Neu V: " & Datum & " " & objItem.Name
End If
End If
Next
cscript //nologo C:\Scripts\Zippen.vbs
bastla
Hallo sascha123!
Deine Zeile ist mir nicht ganz klar - falls es darum geht, einen Dateipfad mit dem aktuellen Datum zu erstellen, würde ich allerdings ohnehin zur Schreibweise "JJJJ-MM-TT" greifen und daher den Pfad etwa so erstellen (funktioniert unabhängig von den Datumseinstellungen des Systems):
Grüße
bastla
Was ist mit der Variable: intSkipped? - Warum muss diese nicht deklariert werden?
Es muss, solange Du nicht "Option Explicit
" verwendest, keine Variable deklariert werden (dann aber alle) ...Deine Zeile ist mir nicht ganz klar - falls es darum geht, einen Dateipfad mit dem aktuellen Datum zu erstellen, würde ich allerdings ohnehin zur Schreibweise "JJJJ-MM-TT" greifen und daher den Pfad etwa so erstellen (funktioniert unabhängig von den Datumseinstellungen des Systems):
counterFile = "\\server\ARCHIV\ZIPPEN am " & Year(Date) & "-" & Right("0" & Month(Date), 2) & "-" & Right("0" & Day(Date), 2) & ".txt"
bastla
Hallos sascha123!
Du brauchst jeweils (für Dateien und Verzeichnisse getrennt) einen Zähler der Art
den Du im "
platzierst.
Nachdem alle Elemente abgearbeitet sind (also im Codeschnipsel oben ganz am Ende nach dem "
Grüße
bastla
Du brauchst jeweils (für Dateien und Verzeichnisse getrennt) einen Zähler der Art
intAlteDatei = intAlteDatei + 1
Then
"-Zweig der AbfrageIf Datum < Alt Then
Nachdem alle Elemente abgearbeitet sind (also im Codeschnipsel oben ganz am Ende nach dem "
Next
") kennst Du dann die jeweiligen Gesamtwerte und kannst sie in die Datei schreiben ...Grüße
bastla
Hallo sascha123!
Das Erstellen und Schreiben würde ich (falls das Ergebnis in eine Zeile soll) kombinieren:
Ansonsten eben:
Je nachdem, ob Du am Ende der Datei noch eine Zeilenschaltung willst, "
Grüße
bastla
Das Erstellen und Schreiben würde ich (falls das Ergebnis in eine Zeile soll) kombinieren:
objFSO.CreateTextFile(counterFile).Write "Alte Verzeichnisse: " & intAlteVerz & vbTab & "Alte Dateien: " & intAlteDatei
Set objcounterFile = objFSO.CreateTextFile(counterFile)
objcounterFile WriteLine "Alte Verzeichnisse: " & intAlteVerz
objcounterFile WriteLine "Alte Dateien: " & intAlteDatei
objcounterFile.Close
Write
" oder "WriteLine
" für die Ausgabe der letzten Zeile verwenden ...Grüße
bastla
Hallo sascha123!
Du solltest die Zeilen 37 und 38 tauschen (da ansonsten unnötiger Weise bei jedem Durchlauf die Datei erstellt wird) ...
Ansonsten: Schreibrechte in der Freigabe hast Du ja sicher, und die Zeile
gibt es auch schon vor der Schleife ...
Grüße
bastla
Du solltest die Zeilen 37 und 38 tauschen (da ansonsten unnötiger Weise bei jedem Durchlauf die Datei erstellt wird) ...
Ansonsten: Schreibrechte in der Freigabe hast Du ja sicher, und die Zeile
counterFile = "\\server\ARCHIV\ZIPPEN am " & Year(Date) & "-" & Right("0" & Month(Date), 2) & "-" & Right("0" & Day(Date), 2) & ".txt"
Grüße
bastla
Hallo sascha123!
Die Zeile 52 sollte nach Zeile 53 folgen (hatte ich aber oben auch schon angemerkt) - den Rest kann ich mir erst später ansehen ...
Grüße
bastla
Die Zeile 52 sollte nach Zeile 53 folgen (hatte ich aber oben auch schon angemerkt) - den Rest kann ich mir erst später ansehen ...
Grüße
bastla
Hallo sascha123!
Was genau willst Du denn mit
erreichen? Da "
Grüße
bastla
Was genau willst Du denn mit
objFolder.SubFolders.Files.Count
SubFolder
" eine Aufzählung der Unterordner des aktuellen "objFolder
" ist, kannst Du die nur mit einer Schleife einzeln abklappern und dann die jeweilige Anzahl (und auch nur der sich unmittelbar darin, nicht aber auch in Unter-Unterordnern befindlichen) "Files
" ermitteln ...Grüße
bastla
Hallo sascha123!
Magst Du vielleicht trotzdem nochmal erklären, was Du eigentlich willst - die Idee, nach jeder einzelnen alten Datei die Anzahl an Dateien im aktuellen Ordner sowie allen Unterordnern zu ermitteln (zumindest interpretiere ich zB die Zeile 43 so) würde ich mal "speziell" nennen, und das dann auch noch in eine Datei schreiben zu wollen, die nach dem letzten derartigen Vorgang geschlossen wurde (Zeile 44) ist "aussichtslos" ...
Grüße
bastla
Magst Du vielleicht trotzdem nochmal erklären, was Du eigentlich willst - die Idee, nach jeder einzelnen alten Datei die Anzahl an Dateien im aktuellen Ordner sowie allen Unterordnern zu ermitteln (zumindest interpretiere ich zB die Zeile 43 so) würde ich mal "speziell" nennen, und das dann auch noch in eine Datei schreiben zu wollen, die nach dem letzten derartigen Vorgang geschlossen wurde (Zeile 44) ist "aussichtslos" ...
Grüße
bastla
Hallo sascha123!
Wenn allerdings auch die Unterordner untersucht werden sollten, müsstest Du einerseits Rekursion verwenden (siehe zB die ähnlich gelagerte Problemstellung hier), und andererseits würden dann die darin gefundenen alten Dateien aber ohnehin ebenfalls in "intAlteDateien" mitgezählt werden ...
Grüße
bastla
wie viele Dateien ... INKLUSIVE Unterordnerinhalt
verstehe ich nicht - die Anzahl der alten Dateien wird ja ohnehin gezählt, und was hätte der Unterordnerinhalt damit zu tun?Wenn allerdings auch die Unterordner untersucht werden sollten, müsstest Du einerseits Rekursion verwenden (siehe zB die ähnlich gelagerte Problemstellung hier), und andererseits würden dann die darin gefundenen alten Dateien aber ohnehin ebenfalls in "intAlteDateien" mitgezählt werden ...
Grüße
bastla