cvoigt
Goto Top

Skript um Dateien samt Ordnerstruktur über SendTo zu verschieben

Hallo,

OS: Win2000 oder XP

ich habe folgendes Problem:
Ich möchte Dateien oder Ordner mit einem Script im Kontektmenü "SendTo" mit der gesammten Ordnerstruktur in ein ArchivVerzeichniss verschieben.

Beispiel:
S:\
?? Archiv
??? Abteilung 1
???? Subdir 1
????? Subdir 1a
???? Subdir 2
???? ...
??
??? Abteilung 2
???? ...
??
??? Abteilung 3
? ?? ...
?
?? Abteilung 1
??? Subdir 1
???? Subdir 1a
??? Subdir 2
??? ...
?
?? Abteilung 2
??? ...
?
?? Abteilung 3
 ?? ...

Der Ordner Archiv ist bisher leer (nur die Abteilungs-Ordner sind angelegt - wg. ACL). Wenn jetzt ein User der Meinung ist, dass er eine bestimmte Datei/Ordner nicht mehr benötigt (aber auch nicht löschen möchte/kann - z.B. wg. Aufbewahrungsfristen HGB usw.), dann soll die Datei/Ordner mit der gesamten Struktur ins Verzeichnis Archiv\Abteilung XY\... verschoben werden.

Ich habe schon ein kleines VB-Script geschrieben, aber leider gibt es ein Problem:
Wenn der User eine Datei schon archiviert hat und später den ganzen Ordner archivieren möchte kommt es zu einem Fehler (nur Dateien oder nur Ordner funktioniert).
'==========================================================================  
'  
' NAME: Dateien archivieren  
' VERSION: 0001  
'  
' AUTOR: Christian Voigt-Sommer  
' DATUM: 14.09.2007  
'  
' Funktion:   
'   
'==========================================================================  
' Änderungen:   
'   
'==========================================================================  

Option Explicit

DIM fso
DIM args
DIM tmp
DIM strQuelle
DIM strQuellPfad
DIM strZielPfad
DIM strArchivPfad

strArchivPfad="D:\TEMP\"  

sChkCScript()

Set fso = CreateObject("Scripting.FileSystemObject")  

Set args=WScript.Arguments
If args.Count>0 Then
   strQuelle=args(0)
   tmp = InStrRev(strQuelle,"\")  
   strQuellPfad = Left(args(0),tmp)
Else
   sSay "Archiviert Dateien in einem vordefiniertem Ordner"  
   sSay "unter Beibehaltung der Ordnerstuktur"  
   sSay ""  
   sSay "Um eine Datei zu verschieben:"  
   sSay "Archiv.vbs [Laufwerk:][Pfad]Datei"  
   sSay ""  
   sSay "Um ein Verzeichniss zu verschieben:"  
   sSay "Archiv.vbs [Laufwerk:][Pfad]Verz"  
   sSay ""  
   sSay "[Laufwerk:][Pfad]Datei   Bezeichnet den Pfad und den Namen der zu"  
   sSay "                         archivierenden Datei(en)."  
   sSay "[Laufwerk:][Pfad]Verz    Bezeichnet das zu archivierende Verzeichnis."  
   sSay ""  
   WScript.Sleep 60*5
   WScript.Quit
End If

strZielPfad=strArchivPfad & mid(strQuellPfad,4,500)

sSay "strArchivPfad: " & strArchivPfad  
sSay "strQuelle: " & strQuelle  
sSay "strQuellPfad: " & strQuellPfad  

sSay ""  
sSay "md " & strZielPfad  
fAusfuehren "cmd.exe /c md " & strZielPfad,"Msg",""  
sSay ""  
sSay "move " & strQuelle & " " & strZielPfad  
fAusfuehren "cmd.exe /c move " & strQuelle & " " & strZielPfad,"Msg",""  

   WScript.Sleep 60*50

'###########################################################################################  
'                                 Beginn Sub und Function  
'###########################################################################################  

'##### Beginn ASCII2ANSI #####  
' Wandelt deutsche Zeichen (Umlaute) um  
Function fASCII2ANSI(text)
Dim temp
	temp = Replace(text, Chr(132), Chr(228))
	temp = Replace(temp, Chr(129), Chr(252))
	temp = Replace(temp, Chr(142), Chr(196))
	temp = Replace(temp, Chr(154), Chr(220))
	temp = Replace(temp, Chr(153), Chr(214))
	temp = Replace(temp, Chr(148), Chr(246))
	temp = Replace(temp, Chr(225), Chr(223))
	fASCII2ANSI = temp
End Function
'##### Ende ASCII2ANSI #####  

 '##### Beginn Ausfuehren #####  
' Ausführen von Programmen oder Betriebssystem-Befehlen  
Function fAusfuehren(strBefehl,strArt,strLogFile)
  Dim objWshShell
  Dim objJob
  Dim strJobErr
  Dim rc
  Dim TMP

  strJobErr = ""  
  Set objWshShell = WScript.CreateObject("Wscript.shell")  
  Set objJob = objWshShell.Exec(strBefehl)

  Do While objJob.status = 0
    TMP = objJob.stderr.readall
    If TMP <> "" Then  
      strJobErr = strJobErr & fASCII2ANSI(TMP)
    End If
  Loop
  rc = objJob.ExitCode

  If strArt="Log" Then  
    If rc <> 0 Then
      sWriteLog strLogFile,"""" & strBefehl & """ (RC: " & rc & ")" & vbCRLF & strJobErr  
    Else
      sWriteLog strLogFile,"Aktion """ & strBefehl & """ erfolgreich abgeschlossen (RC: " & rc & ")"  
    End If
  ElseIf strArt="Msg" Then  
    If rc <> 0 Then
      sSay strBefehl & "(RC: " & rc & ")" & vbCRLF & strJobErr  
    Else
      sSay strBefehl & " erfolgreich abgeschlossen (RC: " & rc & ")"  
    End If 
  End If

  If rc <> 0 Then
    fAusfuehren = rc
  Else
    fAusfuehren = 0
  End If
End Function
'##### Ende Ausfuehren #####  

 '##### Beginn LeftString #####  
' sucht das letzte Zeichen in einem String und gibt alles vor dem Zeichen aus  
Function fLeftString(String,Trennzeichen)
On Error Resume Next
      fLeftString = Left(String,InStrRev(String,Trennzeichen)-1)
On Error Goto 0
End Function
'##### Ende LeftString #####  

 '##### Beginn ChkCScript #####  
' Prüfung, ob Ausführung über CScript.exe  
Sub sChkCScript()
If Not InStr(UCase(WScript.FullName), "CSCRIPT") <> 0 Then  
   MsgBox "Ausführung mit CScript erforderlich!"  
   WScript.Quit
End If
End Sub
'##### Ende ChkCScript #####  

 '##### Beginn Say #####  
' Bildschirmausgabe  
Sub sSay(Msg)
 Wscript.echo Msg
End Sub
'##### Ende Say #####  

Hat jemand eine andere Idee? - darf auch CMD oder BAT sein.

Habe auch schon andere Beiträge mir angeschaut Skript um Dateien samt Ordnerstruktur zu verschieben konnte dies aber nicht auf mein Problem übertragen.

Vielen Dank im Voraus.

MfG
Voigt-Sommer

Content-Key: 68833

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

Printed on: April 25, 2024 at 07:04 o'clock

Member: bastla
bastla Sep 17, 2007 at 22:21:08 (UTC)
Goto Top
Hallo cvoigt!

An sich wäre Batch sicherlich die bessere (oder zumindest einfachere) Sprache für diesen Zweck, aber auch mit reinem VBS sollte sich die Aufgabe lösen lassen:
'==========================================================================  
'  
' NAME: Dateien archivieren  
' VERSION: 0001  
'  
' AUTOR: Christian Voigt-Sommer  
' DATUM: 14.09.2007  
'  
' Funktion:   
'   
'==========================================================================  
' Änderungen:   
'   
'==========================================================================  

Option Explicit

DIM fso, args
DIM strQuelle, strQuellPfad, strZielPfad, strArchivPfad, strFullPath
DIM aPfad, strTeilPfad
DIM IsFolder
DIM sOut
DIM i

strArchivPfad = "Z:\TEMP"  

'sChkCScript()  

Set fso = CreateObject("Scripting.FileSystemObject")  

Set args = WScript.Arguments
If args.Count>0 Then
   strQuelle = args(0)
   If fso.FolderExists(strQuelle) Then 'Datei oder Ordner?  
      IsFolder = True
   ElseIf Not fso.FileExists(strQuelle) Then
      sSay strQuelle & " wurde nicht gefunden."  
	  WScript.Quit
   End If

   strQuelle = fso.GetAbsolutePathName(strQuelle) 'Vollständigen Pfad verwenden  

   If IsFolder Then
      If Not fso.GetFolder(strQuelle).IsRootFolder Then
		 strQuellPfad = fso.GetParentFolderName(strQuelle)
	  Else
	     strQuellPfad = ""  
	  End If
   Else
      strQuellPfad = fso.GetParentFolderName(strQuelle)
	  strFullPath = strArchivPfad & "\" & Mid(strQuelle, 4)  
   End If
Else
   sOut = "Archiviert Dateien in einem vordefiniertem Ordner" & vbCrLF & _  
   "unter Beibehaltung der Ordnerstuktur" & vbCrLF & _  
   "" & vbCrLF & _  
   "Um eine Datei zu verschieben:" & vbCrLF & _  
   "Archiv.vbs [Laufwerk:][Pfad]Datei" & vbCrLF & _  
   "" & vbCrLF & _  
   "Um ein Verzeichniss zu verschieben:" & vbCrLF & _  
   "Archiv.vbs [Laufwerk:][Pfad]Verz" & vbCrLF & _  
   "" & vbCrLF & _  
   "[Laufwerk:][Pfad]Datei" & vbTab & "Bezeichnet den Pfad und den Namen der zu" & vbCrLF & _  
   vbTab & vbTab & vbTab & "archivierenden Datei(en)." & vbCrLF & _  
   "[Laufwerk:][Pfad]Verz" & vbTab & "Bezeichnet das zu archivierende Verzeichnis."  
   sSay sOut
   WScript.Quit
End If

strZielPfad = strArchivPfad & "\" & Mid(strQuellPfad, 4)  
If Right(strZielPfad, 1) <> "\" Then strZielPfad = strZielPfad & "\"  

sOut = "strArchivPfad:" & vbTab & strArchivPfad & vbCrLF & _  
"strQuelle:  " & vbTab & strQuelle & vbCrLF & _  
"strQuellPfad:" & vbTab & strQuellPfad & vbCrLF & _  
"" & vbCrLF & _  
"Erstelle: " & vbTab & strZielPfad  
sSay sOut

aPfad = Split(strZielPfad, "\")  
strTeilPfad = aPfad(0)
For i = 1 To UBound(aPfad) 'Zielpfad aufbauen  
   strTeilPfad = strTeilPfad & "\" & aPfad(i)  
   If Not fso.FolderExists(strTeilPfad) Then
      fso.CreateFolder(strTeilPfad)
   End If
Next

sSay vbCrLF & "Verschiebe " & vbTab & strQuelle & vbCrLF & "nach " &vbTab & vbTab & strZielPfad  
If IsFolder Then
   fso.CopyFolder strQuelle, strZielPfad, True
   fso.DeleteFolder strQuelle
Else
   If fso.FileExists(strFullPath) Then fso.DeleteFile(strFullPath)
   fso.MoveFile strQuelle, strZielPfad
End If

'###########################################################################################  
'                                 Beginn Sub und Function  
'###########################################################################################  

 '##### Beginn ChkCScript #####  
' Prüfung, ob Ausführung über CScript.exe  
Sub sChkCScript()
If Not InStr(UCase(WScript.FullName), "CSCRIPT") <> 0 Then  
   MsgBox "Ausführung mit CScript erforderlich!"  
   WScript.Quit
End If
End Sub
'##### Ende ChkCScript #####  

 '##### Beginn Say #####  
' Bildschirmausgabe  
Sub sSay(Msg)
 Wscript.echo Msg
End Sub
'##### Ende Say #####  
Da keine "Shell"-Befehle verwendet werden (und sich die Ausgaben, falls Du sie tatsächlich benötigst, auch mit MsgBoxes einigermaßen formatieren lassen), sollte als Interpreter nicht unbedingt "cscript.exe" verlangt sein.

Im Vergleich zum "md"-Befehl ist "CreateFolder" auf das schrittweise Erstellen einer Ordnerstruktur beschränkt, daher die Klimmzüge in diesem Teil.
Vielleicht noch der Hinweis, warum es in Deiner Version nicht geklappt hat: Mit "move" kannst Du im Zielverzeichnis bereits existierende Verzeichnisse nicht überschreiben - Du müsstest ein "xcopy /s /y" mit einem "rd /s /q" kombinieren ...

Grüße
bastla
Member: cvoigt
cvoigt Sep 18, 2007 at 19:32:36 (UTC)
Goto Top
Hallo bastla,

danke für Ihre Antwort. Hätte aber noch Fragen.

Wie würden Sie es mit Batch machen?

Ich habe gestern vor Ihrer Antwort (animiert durch den Beitrag auf den ich verwiesen habe) mal ein bischen mit "for" experimentiert:
Set Archivziel=S:\Archiv
for /D %%i in (%1) do set Zielpfad=%%~pi
md "%Archivziel%%Zielpfad%" 2>nul  
move "%1" "%Archivziel%%Zielpfad%"  
pause
Das Ergebnis ist jedoch das gleiche wie in meinem VB-Script (nur kürzer face-smile).

Du müsstest ein "xcopy /s /y" mit einem "rd /s /q" kombinieren ...
Wie sieht dies aus? Ist dass auch Sicher, dass nicht gelöscht wird, obwohl der xcopy irgendwie fehl schlug.
"rd" ist doch nur für Verzeichnisse und nicht für Dateien oder irre ich mich da?
Was ist wenn nur eine einzelne Datei archiviert werden soll?

MfG
Voigt-Sommer
Member: bastla
bastla Sep 18, 2007 at 22:00:03 (UTC)
Goto Top
Hallo cvoigt!

Analog zur Script-Lösung könnte die Batch-Variante so aussehen:
@echo off
if not exist %1 goto :eof

set "Archivziel=S:\Archiv"  
set "Pfad=%~p1"  
set "DoV=%~nx1"  
set "ZPfad=%Archivziel%%Pfad%"  
set "Z=%Archivziel%%Pfad%%DoV%"  

if not exist "%ZPfad%" md "%ZPfad%"  

set V=
dir "%~1\*.*">nul 2>nul && set V=True  
if defined V (
	echo Verzeichnis "%DoV%" wird verschoben nach:  
	echo %ZPfad%
	echo.
	xcopy /s /e /i /y "%~1\*.*" "%Z%" >nul && rd /s /q %1  
) else (
	echo Datei "%DoV%" wird verschoben nach:  
	echo %ZPfad%
	echo.
	move %1 "%Z%"  
) 
pause
Die Unterscheidung zwischen Datei und Verzeichnis ist erforderlich, da nur für Dateien der "move"-Befehl zum gewünschten Ergebnis führt.

Für Verzeichnisse wird, wie schon kurz angedeutet, zunächst der Inhalt (inkl der Unterverzeichnisse) kopiert und, falls der Kopiervorgang ohne Fehler beendet wurde (zur Berücksichtigung dieser Bedingung wird die Verknüpfung der beiden Befehle mit "&&" vorgenommen), das gesamte Verzeichnis (und damit natürlich auch die darin enthaltenen Dateien und Unterverzeichnisse) gelöscht.
Um Ihrer etwaigen Frage nach der Zeile
dir "%~1\*.*">nul 2>nul && set V=True  
zuvorzukommen face-wink:

Der "dir"-Befehl mit zusätzlichem "\*.*" führt bei Anwendung auf ein existierendes Verzeichnis (auch wenn dieses leer ist) zu einer gültigen Ausgabe, während für eine Datei ein Fehler auftritt.

Mit dem oben erwähnten Verknüpfungsoperator "&&" wird bei Beendigung des "dir"-Befehles ohne Fehler der Variablen %V% (welche vorher mit "set V=" gelöscht worden war) ein Wert zugewiesen.

Der Wert selbst ist nicht von Belang, aber die Tatsache, dass die Variable %V% überhaupt einen Wert enthält (und damit "definiert" ist), wird in der nächsten Zeile zur Feststellung der "Verzeichnis-Eigenschaft" des übergebenen Parameters eingesetzt.

Da die Ausgabe des "dir"-Befehles, egal ob mit oder ohne Fehler, nicht interessiert, wird sie für beide Fälle nach "nul" umgeleitet. Ganz exakt wäre die Schreibweise dafür eigentlich "1>nul 2>nul", wobei "2>nul" für das Unterdrücken einer ev Fehlermeldung sorgt.

Grüße
bastla