rotlux
Goto Top

VBS Script zum kopieren mehrerer Dateien die in einem TXT File gelistet sind

Hallo zusammen,

ich habe ein kleines VBScript erstellt, welches mir von allen unseren Servern bzw. Shares eine Auswertung erstellt wo Dateien eines bestimmten Filetyps liegen.

habe nun ein Textfile mit ca. 50.000 Einträgen

Alle Dateien die in diesem File gelistet sind
\\Servername\Share\Ordner\Unterordner\.....\Dateityp.egal
\\Servername\Share\Ordner\Unterordner2\......\Datei.egal
usw....

Jetzt sollte ich folgende Schritte vornehmen: (per VBS Script)
Script A
Alle Dateien aus dem Txt File vom Quellpfad an ein Ziel kopieren.
-> Erzeugung log File bei den Files, die nicht kopiert / gefunden wurden (weil z.B. der User das File zwischenzeitlich umbenannt, gelöscht, ... hat)

(Manuelle Nacharbeit der Files aus dem LogFile)

Script B
Alle Dateien aus dem Txt File löschen

Lässt sich das realisieren?
Vielen Dank
Grüße
Marcel

Content-Key: 162359

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

Ausgedruckt am: 29.03.2024 um 08:03 Uhr

Mitglied: facebraker
facebraker 10.03.2011 um 09:33:06 Uhr
Goto Top
Hi,

ich würde es persönlich mit VB.NET realisieren, das Express ist ja kostenlos.
Da hast du einen Debugger und kannst programmieren.
Und so unterschiedlich ist der Code auch nicht.
Dazu kommt noch du hast schon fertige Dateireader etc.pp. auch das Kopieren läßt sich einfacher schreiben.
Ich erzeuge dann immer Konsolenanwendungen mit Parametern, die ich dann im Taskmanager starten kann.

Gruß Alex
Mitglied: bastla
bastla 10.03.2011 um 09:57:24 Uhr
Goto Top
Hallo rotlux!

Vielleicht postest Du einmal vorweg den aktuellen Stand der beiden Scripts ...

Grüße
bastla
Mitglied: rotlux
rotlux 10.03.2011 um 17:38:12 Uhr
Goto Top
Hallo Bastla,

anbei der Code zu Script 1

'-------------------------------------------------------  
' Filecopy aus Textdatei  
'   
'-------------------------------------------------------  

' #####################################################  
' ###            C H A N G E   L O G                ###  
' #####################################################  
' 07.03.2011 /ma Erstellung des Scriptes   
 

'Variabendefinition  
Option Explicit
Dim fso, file, oFile, strQuelle, StrZiel, StrLog, StrToCopy, objFile, objfso, strLine
Set objFSO = CreateObject("Scripting.FileSystemObject")  


StrZiel = "C:\temp\vbtest\test\ziel\"  
StrLog =  "C:\temp\vbtest\test\logfile.txt"  

StrToCopy = "C:\temp\vbtest\test\tocopy.txt"  


Set objFile = objfso.OpenTextFile(StrToCopy, 1)
Do Until objFile.AtEndOfStream
    strLine = objFile.ReadLine
    FileCopy strLine
Loop
File.Close




'---------------------------------- FUNKTIONEN ----------------------------------  

Function FileCopy(strQuelle)
	Set fso = CreateObject("Scripting.FileSystemObject")  
	if fso.FileExists(strQuelle) then
		fso.CopyFile strQuelle, StrZiel
		set fso = nothing
	else
		Set oFile = fso.OpenTextFile(StrLog,8,true)
		oFile.WriteLine "Folgende Datei wurde nicht gefunden: " & strQuelle  
		oFile.close
		Set fso = nothing
	end if
	Set fso = nothing
End Function


Was es machen sollte

Alle Dateien die in StrToCopy stehen von der Quelle ins Ziel kopieren

Was es leider macht
Nix
Mitglied: rotlux
rotlux 10.03.2011 um 17:55:50 Uhr
Goto Top
habs grad selbst gefunden...
Zeile 29 objFile.Close

Danach funktioniert es soweit


Fürs löschen müsste ich doch nur 38-40 abändern, oder?
Mitglied: Biber
Biber 10.03.2011 um 18:34:22 Uhr
Goto Top
Moin rotlux,

ich will dir da nix Fertiges zusammenschrubbeln, weil ich gar nicht das Gefühl habe, du bekommst es nicht alleine hin.

Aber als Hinweis:

Du deklarierst zwar in einer der ersten Zeilen dein FileSystemObject fso,
weil du das ja auch für den ganzen Quatsch nur ein einziges mal brauchst.
Das finde ich gut.

Allerdings machst du dann doch jedes gatesverdammte Mal in der aufgerufenen DeinFIleCopy()-Unterroutine
  • ein CreateObject(FileSystemObject )
  • ein DestroyObject(FileSystemObject) bzw. set fso = nottingham
Also geplanterweise so 50000 oder 80000mal.

Was in etwa so ökologisch sinnvoll ist wie die FDP.

Da würde ich noch einen Moment drüber nachdenken an deiner Stelle.

Also nich' jezz' über die FDP, mein ich.

Grüße
Biber
Mitglied: 76109
76109 10.03.2011 um 21:43:31 Uhr
Goto Top
Hallo rotlux!

Ja, was möchtest Du den löschen und was hast Du bezüglich Biber's Anmerkungen nun alles geändert?

Gruß Dieter
Mitglied: Biber
Biber 10.03.2011 um 22:10:56 Uhr
Goto Top
Moin didi1954,

das müssten doch nach der obigen Beschreibung alle Dateien sein,
  • die in der LogDatei A = "AllezuKopierenden.log" stehen
  • und die NICHT in der ggf. manuelle nachbearbeiteten LogDatei B = "Broblemfälle.log"
zu find(str)en sind, oder?

Oder darf er für dies VBS-Geraffel nicht vorher mit FindStr eine neue LogDatei C = "ChruppWech.log" erzeugen?

Grüße
Biber
Mitglied: 76109
76109 11.03.2011 um 00:17:43 Uhr
Goto Top
Hallo Biber!

Tja, habe ich wohl irgendwie ein Verständnisproblemface-wink

Sollens jetzt die erfolgreich kopierten Dateien in Quelle sein? Wenn ja, dann wäre ja ein Move möglich oder
sollens die erfolgreich kopierten Dateipfade in der ZuKopierenDatei sein? Oder die jetzt in der LogFile stehen?
Wie auch immer, dann wäre es doch wesentlich einfacher, die Datei innerhalb des Kopiervorgangs (FileExists True/False) einfach neu zu schreiben?

Gruß Dieter
Mitglied: rotlux
rotlux 14.03.2011 um 08:09:37 Uhr
Goto Top
Hallo zusammen,

ich habe das Script verschlimmbessert

Mein Problem ist das in dem Textfile (in dem die Pfade mit Dateinamen stehen evtl. doppelte Dateinamen sein können

z.B.
\\server1\share1\user1\unterordner\meinetolledatei.doc
\\server1\share1\user2\privat\meinetolledatei.doc

würde den Copy daher gerne so gestalten, dass im Ziel ein Ordner angelegt wird
\\zielpfad\user1\unterordner\meinetolledatei.doc
\\zielpfad\\user2\privat\meinetolledatei.doc

irgendwie macht er das aber nicht!?
könnt ihr mir weiterhelfen?

Anbei mein Script


'-------------------------------------------------------  
' Filecopy aus Textdatei  
'-------------------------------------------------------  

' #####################################################  
' ###            C H A N G E   L O G                ###  
' #####################################################  


'Variabendefinition  
Option Explicit
Dim fso, file, oFile, strQuelle, StrZiel, StrLog, StrToCopy, objFile, strLine, strFolder, strFolderLen, strLength, strTrenner, strFilename, strDestination, strdest, objFSO, objFolder, objShell, ObjWshShell

Set objFSO = CreateObject("Scripting.FileSystemObject")  
Set fso = CreateObject("Scripting.FileSystemObject")  

StrZiel = "C:\temp\vbtest\test\ziel"  
StrLog =  "C:\temp\vbtest\test\logfile.txt"  
StrToCopy = "C:\temp\vbtest\test\tocopy.txt"  

Set objFile = objfso.OpenTextFile(StrToCopy, 1)
Do Until objFile.AtEndOfStream
    strLine = objFile.ReadLine
	Folderpath strLine
    FileCopy strLine
Loop
objFile.Close




'---------------------------------- FUNKTIONEN ----------------------------------  

Function FileCopy(strQuelle)
	if fso.FileExists(strQuelle) then
		Set ObjWshShell = WScript.CreateObject("WScript.Shell")  
		'msgbox "CMD robocopy " & Chr(34) & strQuelle & Chr(34) & " " & Chr(34) & strDest & strFilename & Chr(34) & " /s /e"  
		ObjWshShell.Run "robocopy " & Chr(34) & strQuelle & Chr(34) & " " & Chr(34) & strDest & Chr(34) & " /s /e"  
		Set ObjWshShell = Nothing
	else
		Set oFile = fso.OpenTextFile(StrLog,8,true)
		oFile.WriteLine "Folgende Datei wurde nicht gefunden: " & strQuelle  
		oFile.close
		Set fso = nothing
	end if
End Function

Function Folderpath(strLine)
	strFolderLen = Len(strLine)
	strLength = strFolderLen - 2
	strFolder = Right(strLine, strLength)
	strTrenner = InStrRev(strFolder,"\")  
	strDestination = Left(strFolder, strTrenner)
	strFilename = Right(strFolder, strTrenner)
	strDest = StrZiel & strDestination
End Function
Mitglied: 76109
76109 14.03.2011 um 15:38:11 Uhr
Goto Top
Hallo rotlux!

Erstmal zur Information:
Wenn Du im Haupt-Code Dim-Variablen deklarierst, dann behalten diese im gesamten Skript ihre Gültigkeit, sofern in Sub's oder Functionen nicht der gleiche Variablen-Name nocheinmal per Dim-Anweisung verwendet wird. Biber hat Dir ja schon zu erklären versucht, dass es vollkommen unnötig ist, ein Object (Fso,Shell...) bei jedem Aufruf erneut einer Variablen zuzuweisen. Einmal im Haupt-Code reicht völlig aus.

Hier mal ein Beispiel, wie es funktionieren könnte/sollte (Konstanten entsprechen anpassen):
Option Explicit

Const strLogPath = "C:\temp\vbtest\test\logfile.txt"  
Const strTextPath = "C:\temp\vbtest\test\tocopy.txt"  
Const strDestPath = "C:\temp\vbtest\test\ziel"  

Dim objFso, objShell, objLogFile, objTextFile, arrFileList, strFile

Set objShell = CreateObject("WScript.Shell")  
Set objFso = CreateObject("Scripting.FileSystemObject")  

Set objLogFile = objFso.CreateTextFile(strLogPath)
Set objTextFile = objFso.OpenTextFile(strTextPath)

'Alle Textzeilen aus ToCopy-File in Array einlesen  
arrFileList = Split(objTextFile.ReadAll, vbCrLf)

'ToCopy-File neu erstellen  
Set objTextFile = objFso.CreateTextFile(strTextPath)
    
'Erstellt am in Log-File schreiben  
objLogFile.WriteLine "Erstellt am " & Now & vbCrLf  

'Dateipfade einlesen/auswerten/kopieren  
For Each strFile In arrFileList
    If strFile <> "" Then 'Test Leerzeile  
        If objFso.FileExists(strFile) Then 'Test ob Datei existiert  
            objTextFile.WriteLine strFile
            Call CopyFile1(strFile)
        Else
            objLogFile.WriteLine "Datei nicht gefunden:" & vbCrLf & vbTab & strFile  
        End If
    End If
Next

objTextFile.Close: objLogFile.Close

Sub CopyFile1(ByRef strSourceFile)
    Dim strDestFolder, strCmd, intPos
    
   'Position des '\' im Quell-Ordnerpfad in Abhängigkeit von 'X:\' oder '\\' festlegen  
    If Mid(strSourceFile, 2, 1) = ":" Then intPos = 3 Else intPos = 2  
    
   'Ziel-Ordnerpfad fetlegen  
    strDestFolder = objFso.GetParentFolderName(strDestPath & Mid(strSourceFile, intPos)) & "\"  
    
   'Kopierbefehl zusammenstellen  
    strCmd = "xcopy """ & strSourceFile & """ """ & strDestFolder & """"  
        
   'Kopierbefehl ohne Dos-Fenster absetzen und auf Exit warten  
    If objShell.Run(strCmd, 0, True) <> 0 Then 'Exit <> 0 Copy-Fehler  
        objLogFile.WriteLine "Datei konnte nicht kopiert werden:" & vbCrLf & vbTab & strSourceFile  
    End If
End Sub

Sub CopyFile2(ByRef strSourceFile)
    Dim strSrcFolder, strDstFolder, strSrcFile, strCmd, intPos
    
   'Position des '\' im Quell-Ordnerpfad in Abhängigkeit von 'X:\' oder '\\' festlegen  
    If Mid(strSourceFile, 2, 1) = ":" Then intPos = 3 Else intPos = 2  
    
   'Quell- und Ziel-Parameter fetlegen  
    strSrcFolder = objFso.GetParentFolderName(strSourceFile)
    strDstFolder = objFso.GetParentFolderName(strDestPath & Mid(strSourceFile, intPos))
    strSrcFile = objFso.GetFileName(strSourceFile)
        
    strCmd = "robocopy """ & strSrcFolder & """ """ & strDstFolder & """ """ & strSrcFile & """"  
        
    If objShell.Run(strCmd, 0, True) <> 1 Then 'Exit <> 1 Copy-Fehler   
        objLogFile.WriteLine "Datei konnte nicht kopiert werden:" & vbCrLf & vbTab & strSourceFile  
    End If
End Sub

Zum Ablauf:
Die Datei "ToCopy.txt" wird zu Begin auf einen Schlag in ein Array eingelesen und anschließend überschrieben. D.h. am Ende beinhaltet diese Datei nur noch Pfade, die auch existieren. In der Log-Datei werden zum einen, die nicht existierenden Pfade gelistet und zum anderen Pfade von Dateien, die nicht kopiert werden konnten (Run-Exit-Fehler).

Desweiteren habe ich mal 2 Copy-Subs verwendet/getestet, einmal mit XCopy und einmal mit RoboCopy. Da ja jede Datei einzeln kopiert wird, sollte XCopy eigentlich ausreichen, aber die Entscheidung überlasse ich natürlich Dir.

Von der Datei ToCopy solltest Du vor dem Testen erst noch eine Sicherungskopie anlegen.

Gruß Dieter

[edit] Code geändert [/edit]
Mitglied: Biber
Biber 14.03.2011 um 21:07:05 Uhr
Goto Top
Moin rotlux,

auch von mir noch eine Ergänzung.
Ganz besonders das FileSystemObject mit seinen vielen, vielen tonnenweise dokumentierten Baukasten-Methoden,
die dann auch nur das altbekannte COPY/DEL/MOVE/MD/RD mit anderen Vokabeln ausdrücken
-> diese Spielwiese ist allerbest zum pflegeleichten Einstieg ins VBSkripting.
Sowas wie CERN früher für Hacker war oder die Jugendfeuerwehr für kleine Machos.

Und nachdem dir ja didi1954 schon ein paar Steinchen, so ca. 98 von 100, aus dem Weg geräumt hat
-> versuch dich doch mal daran, diese merkwürdig draufgepappt anmutende "XCopy"- oder gar "RoboCopy"-Krücke mit den FSO-Methoden hinzubekommen.

Denn a) das schaffst du das b) sieht es mit "RoboCopy"-Aufruf definitiv aus wie gewollt und nicht getraut und c) steht immer im Notfall Hilfe bereit in diesem Forum.

Grüße
Biber
Mitglied: rotlux
rotlux 16.03.2011 um 15:45:23 Uhr
Goto Top
Hallo Didi1954,

vielen Dank für deine Hilfe. Bei mir steht jetzt aber im Log
Trenn-Ordner 'C:\temp\vbtest\test\share' nicht vorhanden:
C:\temp\vbtest\test\quelle\Microsoft Office Excel-Arbeitsblatt (neu).xlsx

C:\temp\vbtest\test\share:
Habe Zeile 07 daraufhin angepasst
Const strSplitFolder = "C:\temp\vbtest\test\share" 'Trenn-Ordner

Woran kann das liegen?
Grüße
Marcel
Mitglied: 76109
76109 16.03.2011 um 16:30:29 Uhr
Goto Top
Hallo rotlux!

Von Deinem Beispiel ausgehend für Quelle:
\\server1\share\user1\unterordner\meinetolledatei.doc
\\server1\share\user2\privat\meinetolledatei.doc
und Ziel:
\\zielpfad\user1\unterordner\meinetolledatei.doc
\\zielpfad\user2\privat\meinetolledatei.doc
sollte ja aus dem Quell-Pfad nur der Teil ab \User\... übernommen werden.

Von daher bin ich davon ausgegangen, das alle Quell-Pfade einen Bezugs-Ordner 'share' enthalten. Es muss ja einen Bezugspunkt geben, woher soll man sonst wissen, ab welchem Ordner in Quelle der restliche Pfad nach Ziel übernommen werden soll?

Wenn also nicht alle Pfade den Bezugs-Ordner 'share' enthalten, dann kann man so machen, dass erst der Teil nach einer konstanten Anzahl von '\'-Zeichen (z.B. ab dem 4. '\') übernommen werden soll, wobei dann allerdings festgelegt werden muss, ob alle Pfade nun mit 'X:\..\..' oder mit '\\..\..' beginnen?

Gruß Dieter
Mitglied: rotlux
rotlux 16.03.2011 um 17:15:42 Uhr
Goto Top
Hallo Dieter,
dann habe ich mich wohl falsch ausgedrückt

es gibt verschiedene Server und verschiedene Shares
zb
\\servername1\sharexy
\\servername1\shareyz
\\servername2\shareabc
\\servername3\test
\\servername3\test2

eigentlich könnte das Script als Ziel immer eine Konstante haben
z.B. Const strDestPath = "C:\temp\vbtest\test\ziel"
und darin dann die Ordner + Files erstellen lassen
Bsp:

C:\temp\vbtest\test\ziel\servername1\sharexy
C:\temp\vbtest\test\ziel\servername1\shareyz
C:\temp\vbtest\test\ziel\servername2\shareabc
C:\temp\vbtest\test\ziel\servername3\test
C:\temp\vbtest\test\ziel\servername3\test2

eigentlich könnte er die "\\" für den Split nehmen!?
Mitglied: 76109
76109 16.03.2011 um 18:31:36 Uhr
Goto Top
Hallo rotlux!

eigentlich könnte das Script als Ziel immer eine Konstante haben z.B.:
Const strDestPath = "C:\temp\vbtest\test\ziel"
Ziel hat bereits ne Konstante (siehe Const in Codezeile 5) und stellt ja auch kein Problem da

Und von Quelle jetzt doch den kompletten Pfadface-wink

Letzten Code oben geändert. Der Quell-Pfad darf der Einfachheit halber mit 'X:\' oder '\\' beginnen. So ist es auch einfacher zu testenface-wink

Gruß Dieter
Mitglied: rotlux
rotlux 17.03.2011 um 11:29:35 Uhr
Goto Top
Hallo Dieter,

Script funktioniert jetzt super! Vielen Dank

Das würde bedeuten, ich kann den Befehl in Zeite 48 von xcopy auch in del abändern und anstatt kopieren würde er alle Files aus dem txt file am vorgegebenen Ort löschen!?

Grüße
Marcel
Mitglied: bastla
bastla 17.03.2011 um 12:11:10 Uhr
Goto Top
Hallo rotlux!

Eher auf "%comspec% /c del" (ist ein interner Befehl) - aber wozu CMD bemühen? Löschen könnte doch VBS selbst ...

Grüße
bastla
Mitglied: 76109
76109 17.03.2011 um 13:19:33 Uhr
Goto Top
Hallo rotlux!

Und ergänzend zu bastla's Kommentar - wie Biber sagen würde face-wink - den WG-mortadellafarbenen Gelöst-Haken nicht vergessen!

Gruß Dieter
Mitglied: Biber
Biber 18.03.2011 um 14:18:04 Uhr
Goto Top
Moin rotlux,

und ergänzend zu bastlas und didi1954s Kommentaren - eigentlich am Liebsten wäre mir das erwähnte Häkchen noch in diesem Leben.

Beispielsweise JETZT.

Schönes Wochenende allen
Biber