ich bin ein totaler Scripting-Anfänger und benötige ein vbs für folgende
Aktion:
Es sollen mit Hilfe von delage32.exe alle Dateien in speziellen Ordnern
gelöscht werden, die älter als 30 Tage sind. Wählbar soll eben der
"spezielle Ordnername" sein, nur in diesen Ordnern soll der
delage32-Befehl ausgeführt werden.
Die Odnerstruktur sieht z.B. so aus:
D:\Verzeichnis1\x
D:\Verzeichnis1\y
D:\Verzeichnis1\zzz
D:\Verzeichnis2\x
D:\Verzeichnis2\y
D:\Verzeichnis2\zzz
D:\Verzeichnis3\x
D:\Verzeichnis3\y
D:\Verzeichnis3\zzz
Nun möchte ich in allen Verzeichnissen D:\*\zzz die alten Dateien per
delage32.exe löschen lassen. Kann mir hier jemand auf die schnelle
helfen? Danke!
Gruss,
Timo
Versuch's mal mit dem folgenden Script. Er besorgt gleich alles, du brauchst
also delage.exe nicht mehr. Hier die Anweisungen dazu:
- Den Script in c:\Löschen.vbs speichern.
- Die Zeilen 2 bis 5 deinem Umfeld anpassen.
- Die englischen Texte auf Deutsch übersetzen (falls gewünscht).
- Die Zeilennummern entfernen.
- Eine Befehlseingabe öffnen (Start / Run / cmd).
- Denn folgenden Befehl tippen: cscript //nologo c:\Löschen.vbs
- Dich vergewissern, dass alles wie gewünscht läuft. Vorläufig wird nichts
gelöscht!
- In Zeile 1 Active = True setzen.
- Den Script nochmals laufen lassen. Jetzt wird er alte Dateien löschen.
01. Const Active = False
02. Const MaxAge = 10 'days
03. Const Recursive = True
04. Const sOrdner = "zzz"
05. Const sLaufwerk = "D:\"
06.
07. Checked = 0
08. Deleted = 0
09.
10. if active then verb = "Deleting """ Else verb = "Old file: """
11.
12. Set oFSO = CreateObject("Scripting.FileSystemObject")
13.
14. For Each oOrdner In oFSO.GetFolder(sLaufwerk).SubFolders
15. For Each oUnterordner In oOrdner.SubFolders
16. If LCase(oUnterordner.Name) = sOrdner _
17. Then CheckFolder(oUnterOrdner)
18. Next
19. Next
20.
21. WScript.echo
22. if Active then verb = " file(s) deleted" _
23. Else verb = " file(s) would be deleted"
24. WScript.Echo Checked & " file(s) checked, " & Deleted & verb
25.
26. Sub CheckFolder (oFldr)
27. For Each oFile In oFldr.Files
28. Checked = Checked + 1
29. If DateDiff("D", oFile.DateLastModified, Now()) > MaxAge Then
30. Deleted = Deleted + 1
31. WScript.Echo verb & oFile.Path & """"
32. If Active Then oFile.Delete
33. End If
34. Next
35.
36. if not Recursive then Exit Sub
37. For Each oSubfolder In oFldr.Subfolders
38. CheckFolder(oSubfolder)
39. Next
40. End Sub
das script sieht super aus, danke! könntest du jetzt noch einbauen dass
auch leere unterverzeichnisse (natürlich wieder nur im verzeichnis
"zzz") gelöscht werden?
danke & gruss,
timo
oh und noch was hab ich eben bemerkt, wenn ich statt "zzz" ein
verzeichnis mit namen "@datensicherung" nehme funktioniert das script
nicht mehr, liegt wohl an dem "@". gibts dafür auch eine lösung? ausser
das umbenennen der ganzen ordner mit "@" ;)
gruss,
timo
Eigentlich sind Newsgroups als Hilfe gedacht, als Anstoss, um Probleme zu
lösen, mit denen man noch nicht so vertraut ist. Da mein Script 100% deines
ursprünglichen Pflichtenheftes löste und 99% des erweiterten Heftes,
könntest du mit ein wenig Nachdenken und Experimentieren den Rest mit
Leichtigkeit selber entwickeln und dabei erst noch herausfinden, wie das
Script funktioniert - vor allem, weil du die Sache dank "Active = false"
gefahrlos testen kannst. Die folgenden Funktionen sollten dir dabei helfen:
oFSO.GetFolder(oFldr).Files.Count
oFSO.DeleteFolder(oFldr)
Übrigens - ob deine Ordner "zzz" oder "@datensicherung" heissen, spielt
keine Rolle - ich hab's eben speziell für dich getestet. Allerdings musst du
den Ordnernamen mit kleinen Buchstaben schreiben, oder ihn später im
Programm auf Kleinbuchstaben übersetzen.
danke für deine bisherige hilfe, leider komme ich aber nicht wirklich
weiter. ich bin einfach kein programmierer und mit vbs kenn ich mich
schon gleich überhaupt nicht aus.
ich hab dein script nochmals getestet und es klappt einfach nicht egal
ob ich gross- oder kleinschreibung verwende. kannst du mir vielleicht
trotz allem nochmal einen tipp geben? danke!
gruss,
timo
Kann ich, aber dazu muss ich deine Variante meines Scripts sehen, samt dem
Output des Befehls "dir c:\xxxxx", damit ich weiss, wie deine Ordner
heissen. Du musst natürlich "c:\xxxxx" mit dem richtigen
Laufwerk/Ordnernamen ersetzen.
ich verstehe zwar nicht ganz was du genau sehen möchtest aber hier mal
die daten im kopf des scriptes, ansonsten habe ich dein originalscript
genutzt:
Const Active = False
Const MaxAge = 10 'days
Const Recursive = True
Const sOrdner = "@datensicherung"
Const sLaufwerk = "G:\Betrieb"
Unterhalb des Ordners G:\Betrieb gibt es x weitere Unterordner mit
wiederum x weiteren Unterordner, das Verzeichnis in dem gelöscht werden
soll heisst immer "@datensicherung" und ist in verschiedenen
Verzeichnisebenen unterhalb von G:\Betrieb zu finden. Die Verzeichnisse
unterhalb von G:\Betrieb sind manchmal mit Grossbuchstaben am Anfang,
manchmal komplett klein geschrieben.
Als Ausgabe deines Scriptes erhalte ich immer 0 zu löschende Files.
Gruss,
Timo
Du schreibst:
Const sLaufwerk = "G:\Betrieb"
"G:\Betrieb" ist aber kein Laufwerk, sondern ein Verzeichnis! Ganz am Anfang
schriebst du: "Nun möchte ich in allen Verzeichnissen D:\*\zzz die alten
Dateien löschen", und genau dies tut mein Programm, sofern du
Const sLaufwerk = "G:\"
schreibst, wie es sich für ein Laufwerk gehört.
na dann habe ich mich wohl einfach nur falsch ausgedrückt. ich möchte in
einem verzeichnis "betrieb" auf dem laufwerk "g" alle ordner und
unterodner durchsuchen lassen und in gefudnenen ordnern
"@datensicherung" alle dateien älter x tage löschen, zudem alle leeren
ordner in diesem ordner "@datensicherung". stimmts jetzt? ;)
gruss,
timo
noch ein problem taucht auf: das script auf einem windows server 2003
funktioniert nur, wenn ich das durchsuchende laufwerk auf c:\ setze,
jede andere partition auf dem server geht nicht (-> laufzeitfehler:
erlaubnis verweigert).
angemeldet bin ich als administrator, welcher natüürlich auch
vollzugriff auf alle laufwerke hat. welches recht benötige ich denn noch?
gruss,
timo
Na ja, dann wäre es wohl am besten, wenn wir uns Hammer und Nagel besorgen
und dieses Projekt mal richtig festnageln. Dein neustes Pflichtenheft
scheint folgendes auszusagen:
1. Das Verzeichnis "G:\Betrieb" soll durchsucht werden.
2. Bloss Unterverzeichnisse mit Namen "@datensicherung" sollen behandelt
werden, also
G:\Betrieb\@datensicherung
G:\Betrieb\März\@datensicherung
G:\Betrieb\Mai\2008\@datensicherung
aber nicht
G:\Betrieb\Feb2008
und auch nicht
G:\Rechnungen\@datensicherung
3. In jedem der behandelten Unterverzeichnisse sollen alle Dateien, die
älter als x Tage sind, gelöscht werden, also z.B.
G:\Betrieb\@datensicherung\Bestellungen.xls
G:\Betrieb\März\@datensicherung\2009\Rechnungen.xls
G:\Betrieb\März\@datensicherung\2009\Ausstehend\Eingang.xls
Der Vorgang soll rekursiv ablaufen.
4. Wenn ein behandeltes Unterverzeichnis keine Dateien mehr enthält, dann
soll es gelöscht werden, auch wenn es noch weitere leere Unterverzeichnisse
enthält. Wenn tief im Unterverzeichnis noch mindestens eine Datei vorhanden
ist, dann darf das Unterverzeichnis nicht gelöscht werden.
Zu deiner Erlaubnisfrage auf höheren Laufwerken als C: - Dies ist nicht ein
Script-Problem, sondern ein Erlaubnisproblem. Du musst die Bewilligungen
eben so einstellen, dass du Dateien und Verzeichnisse von Explorer aus
manipulieren kannst. Wenn's dort geht, dann funktioniert's mit dem Script
auch!
besser hätte ich es nicht ausdrücken können, das pflichtenheft stimmt
genau :)
komischerweise kann ich die dateien per explorer löschen, nur das script
steigt sofort aus.
gruss,
timo
hi pegasus,
kannst du mir denn nvielleicht nochmal bei meinem neuen pflichtenheft
helfen? wäre klasse.
gruss,
timo
Eigentlich hätte das Pflichtenheft von dir kommen sollen, dann hätte ich die
Sache nicht zwei Mal schreiben müssen. Versuch's Mal mit diesem Script, und
zwar von der Befehlseingabe aus, damit du die Fehlermeldungen sehen kannst.
01. Const Active = False
02. Const MaxAge = 10 'Tage
03. Const Recursive = True
04. Const sOrdner = "D:\Betrieb"
05. Const Name = "@Datensicherung"
06.
07. checked = 0
08. FDeleted = 0
09. ODeleted = 0
10. sName = LCase(Name)
11. Dim sOrdnerListe, iFileCount
12. if active then verb = "Datei löschen: """ Else verb = "Alte Datei: """
13.
14. Set oFSO = CreateObject("Scripting.FileSystemObject")
15. Set oOrdner = oFSO.GetFolder(sOrdner)
16.
17. CompileFolderList oOrdner
18. aOrdnerListe = Split(sOrdnerliste, "|")
19. For i = 0 To UBound(aOrdnerListe) - 1
20. ProcessFolder aOrdnerListe(i)
21. iFileCount = 0
22. CountFiles aOrdnerListe(i)
23. On Error Resume Next
24. If Active And (iFileCount = 0) Then
25. WScript.Echo "Der Ordner """ & aOrdnerListe(i) & """ wird gelöscht"
26. oFSO.DeleteFolder(aOrdnerListe(i))
27. If Err.number = 0 Then
28. ODeleted = ODeleted + 1
29. Else
30. WScript.Echo "Fehler beim Löschen von """ & aOrdnerListe(i) & """"
31. WScript.Echo Err.Description
32. End If
33. End If
34. On Error Goto 0
35. Next
36.
37. If Active Then
38. WScript.Echo checked & " Datei(en) geprüft, " _
39. & FDeleted & " Datei(en) gelöscht"
40. WScript.Echo ODeleted & " Ordner gelöscht"
41. Else
42. WScript.Echo checked & " Datei(en) geprüft, " _
43. & FDeleted & " Datei(en) würden gelöscht"
44. End If
45.
46. '-----------------------------------------------------------------
47. 'Compile a list of all foldes that match the specified folder name
48. '-----------------------------------------------------------------
49. Sub CompileFolderList (oOrdner1)
50. For Each oOrdner2 In oOrdner1.subfolders
51. If LCase(oOrdner2.name) = sName _
52. Then sOrdnerListe = sOrdnerListe & oOrdner2.path & "|"
53. CompileFolderList oOrdner2
54. Next
55. End Sub
56. '--------------------------------------------
57. 'Delete all old files in the specified folder
58. '--------------------------------------------
59. Sub ProcessFolder (sOrdner)
60. For Each oFile In oFSO.GetFolder(sOrdner).Files
61. checked = checked + 1
62. If DateDiff("D", oFile.DateLastModified, Now()) > MaxAge Then
63. WScript.Echo verb & oFile.Path & """"
64. On Error Resume Next
65. If Active Then oFile.Delete
66. If Err.number = 0 Then
67. FDeleted = FDeleted + 1
68. Else
69. WScript.Echo "Fehler beim Löschen von """ & oFile.Path & """"
70. WScript.Echo Err.Description
71. End If
72. On Error Goto 0
73. End If
74. Next
75.
76. if not Recursive then Exit Sub
77. For Each oSubfolder In oFSO.GetFolder(sOrdner).Subfolders
78. ProcessFolder oSubfolder.Path
79. Next
80. End Sub
81. '---------------------------------------------------
82. 'Recursively count the files in the specified folder
83. '---------------------------------------------------
84. Sub CountFiles (sOrdner)
85. iFileCount = iFileCount + oFSO.GetFolder(sOrdner).Files.Count
86. For Each oOrdner1 In oFSO.GetFolder(sOrdner).SubFolders
87. CountFiles oOrdner1.Path
88. Next
89. End Sub
dieses script funktioniert super ohne fehlermeldung :) danke nochmal!
gruss,
timo
Danke für die Rückmeldung.
hm jetzt hab ich doch noch ein kleines problemchen, das script löscht
auch den ordner @datensicherung wenn dieser leer ist, dabei sollen nur
alle leeren verzeichnisse unterhalb dieses ordners gelöscht werden,
nicht der ordner selbst.
wo kann ich hier noch ansetzen?
gruss,
timo
Für dein kleineres Problem gibt's natürlich eine ganz einfache Lösung. Füg
in Zeile 45 zwei neue Zeilen ein: Die erste benützt die Methode
"oFSO.FolderExists", um festzustellen, ob der Ordner noch existiert, und die
zweite erstellt den Ordner neu, falls nötig.
oh je auf die gefahr hin dass ich dich nerve ich bin totaler
programmier-noob, kannst du vielleicht ein wenig konkreter werden? ;)
ich glaube Pegasus meinte sowas in der Art wie
If not oFso.FolderExists(Foldervarible) then oFso.CreateFolder(Foldervarible)
Da ich mir den Code oben noch nicht weiter angeschaut habe, kann ich auch nicht konkreter werden...
Gruß
Dirk
Netterweise hat dir Dirk während meiner Abwesenheit weitere Details
geliefert.
Für zukünftige Fragen schlage ich vor, dass du ein bisschen über den Zweck
dieser Newsgroup nachdenkst. Ich würde sagen, dass sie vor allem drei Zwecke
hat:
- Knifflige Script-Fragen zu beantworten
- Erfahrungen auszutauschen
- Anfängern eine helfende Hand zu reichen
Anderseits glaube ich nicht, dass es sich hier um einen
Gratis-Pizza-Lieferdienst handelt, mit dem sich jeder kostenfrei ein
Programm schreiben lassen kann. Dein Programm mit seinen 90 Zeilen und den
verschiedenen Änderungen war ja nicht eben eine triviale Übung. Für deine
zukünftigen Projekte sehe ich die folgenden Alternativen:
a) Du bezahlst jemanden für seine Kenntnisse, Zeit und Mühe;
b) Du eignest dir Programmierkenntnisse an;
c) Du führst die Unterhaltsarbeiten von Hand aus, statt sie mit einem Script
zu automatisieren.
Ich empfehle dir, Alternative b) in Betracht zu ziehen. Programmieren mit VB
Script kann hochinteressant sein, und von dieser Newsgroup wirst du jede
Menge von Unterstützung bekommen.
Hallo,
ich hab nun nochmals versucht mit diesen zwei Möglichkeiten mein
vorhaben zu erreichen:
1. nach deinem hinweis und dem tip von dirk folgendes in zeile 45 eingefügt:
If not oFso.FolderExists("@datensicherung") then
oFso.CreateFolder("@datensicherung")
Leider wird der Ordner nicht erstellt.
2. die Zeile 24 geändert in
If Active And (iFileCount = 0) AND (aOrdnerListe(i) <>
"@datensicherung") Then
Leider hilft auch dies nicht, der Ordner wird trotzdem gelöscht.
Wie kann ich mich weiter schlau machen warum dies nicht funktioniert?
Gruss,
Timo
kann mir hier niemand weiter helfen?
gruss,
timo
> > 1. nach deinem hinweis und dem tip von dirk folgendes in zeile 45
> > eingefügt:
> >
> > If not oFso.FolderExists("@datensicherung") then
> > oFso.CreateFolder("@datensicherung")
> >
> > Leider wird der Ordner nicht erstellt.
Naja, hier solltest du schon einen kompletten Pfad bereithalten... G:\Betrieb\Mai\@datensicherung
Das könnte der Grund sein, weshalb es nicht gezündet hat.
Du müsstest den Pfad also so in der Art sOrdner & Name übergeben.
> >
> > 2. die Zeile 24 geändert in
> >
> > If Active And (iFileCount = 0) AND (aOrdnerListe(i) <>
> > "@datensicherung") Then
> >
> > Leider hilft auch dies nicht, der Ordner wird trotzdem gelöscht.
> >
> > Wie kann ich mich weiter schlau machen warum dies nicht funktioniert?
ist der Ordnername immer so geschrieben?
Geb dir einfach mal aOrdnerListe(i) in einer msgbox aus.
msgbox aOrdnerListe(i). Dann kannst du sehen, ob das alles auch wirklich so passt.
Wenn es ein Gross/Kleinschreibungsproblemchen gibt könntest du diesem bei der Überprüfung mit lcase() entgegenwirken.
also so in der Art...
instr(lcase(aOrdnerListe(i)), "@datensicherung") > 0
Gruß
Dirk
>>> If not oFso.FolderExists("@datensicherung") then
>>> oFso.CreateFolder("@datensicherung")
>>>
>>> Leider wird der Ordner nicht erstellt.
>
> Naja, hier solltest du schon einen kompletten Pfad bereithalten... G:\Betrieb\Mai\@datensicherung
>
> Das könnte der Grund sein, weshalb es nicht gezündet hat.
>
> Du müsstest den Pfad also so in der Art sOrdner & Name übergeben.
du hast recht, da ist natürlich immer der ganze pfad dabei. hier gibt
nun es das problem, dass in keinem unterordner der ordner
@datensicherung exisitiert und daher immer ein ordner erstellt wird,
daher ist wohl der andere lösungsweg besser:
> also so in der Art...
> instr(lcase(aOrdnerListe(i)), "@datensicherung") > 0
ich hab nun die zeile geändert:
If Active And (iFileCount = 0) AND (instr(lcase(aOrdnerListe(i)), sName)
> 0) Then
das funktioniert so, nur blöderweise ist der string @datensicherung
natürlich in jedem pfad vorhanden, es sollen aber nur die unterordner
gelöscht werden und nicht der ordner @datensicherung selbst.
gibt es eine funktion ähnlich der instr die vom ende des pfades an
vergleicht und nicht vom anfang? dann könnte ich so das problem umgehen
wenn ich quasi nur die letzten 15 zeichen überprüfe ;)
gruss,
timo
> gibt es eine funktion ᅵhnlich der instr die vom ende des pfades an
> vergleicht und nicht vom anfang? dann kᅵnnte ich so das problem umgehen
> wenn ich quasi nur die letzten 15 zeichen ᅵberprᅵfe ;)
Du kᅵnntest natᅵrlich mit right(string, 15) die letzten 15 Zeichen von einem String nehmen.
oder du kᅵnntest mit
mid(string, instrrev(string, "\") +1, (len(string) - len(instrrev(string, "\")) -1))
das Ganze ein wenig variabler gestalten.
(Anm. Die Zeile habe ich gerade aus dem Kopf geschrieben... Muss also nicht unbedingt direkt so funktionieren und syntaktisch
stimmen. Sollte aber als Impression wie man das machen kann durchaus tauglich sein...)
Optional kᅵnnte auch ein Array gehen... Dᅵ kᅵnntest mit split(String, "\") den Pfad zerlegen. Das ist aber, denke ich, evtl. ein
wenig am Thema vorbei.
Gruᅵ
Dirk
> Du könntest natürlich mit right(string, 15) die letzten 15 Zeichen von einem String nehmen.
>
> oder du könntest mit
>
> mid(string, instrrev(string, "\") +1, (len(string) - len(instrrev(string, "\")) -1))
>
> das Ganze ein wenig variabler gestalten.
ich habe die zeile nun so gestaltet:
If Active And (iFileCount = 0) AND
(instr(lcase(right(aOrdnerListe(i),15)), sName) = 0) Then
damit funktioniert es wie gewünscht. danke für deine hilfe!
gruss,
timo
>
> damit funktioniert es wie gewᅵnscht. danke fᅵr deine hilfe!
dank nicht mir, dank Pegasus, der hat die Hauptarbeit geleistet :-)
Gruᅵ
Dirk
hab ich zwar schon, aber gerne bedanke ich mich auch bei pegasus nochmals :)
gruss,
timo