Hallo zusammen,
bisher habe ich eine Filecopy Funktion vermisst, die wie das Standard FileCopy funktioniert, aber nicht bei Konflikten mit einer vorhandenen Zieldatei scheitert. Insbesondere sollte beim Kopieren - analog zum Explorer - die Option bestehen einfach die neue Zieldatei um ein "... (n)" vor der Extension zu ergänzen.
Deshalb stelle ich hier meine private UDF zur Diskussion.
#include-once
#include <File.au3>
#include <Array.au3>
; =========================================================================================================
; _SaveFileCopy($Parm_Src, $Parm_Dest, $Parm_Flag=0)
;
; Funktion: Kopiert eine oder mehrere Datei(en).
;
; $Parm_Src: Die Quelldatei(en) - Wildcards werden unterstützt.
;
; $Parm_Dest: Das Zielverzeichnis der zu kopierenden Datei(en).
;
; $Parm_Flag [optional]: Dieses Flag bestimmt, ob Dateien überschrieben werden, falls sie schon bestehen.
; $Parm_Flag kann eine Kombination der folgenden sein:
; 0 = (Standard) bestehende Dateien nicht überschreiben
; 1 = Überschreiben bestehender Dateien
; 8 = Erstellt die Zielverzeichnisstruktur, falls diese nicht besteht.
;
; Bemerkung: Wenn Flag eine gerade Zahl ist und die Zieldatei schon existiert, wird der Zielname um ein
; ' (n)' vor der Dateierweiterung ergänzt (n = Zahl ab 2, wobei Zielname noch nicht existiert)
; analog zum Verhalten des Windows Explorers mit der Option beide Dateien behalten.
;
; Rückgabe: Erfolg - Gibt 1 zurück.
; Fehlerfall - Gibt 0 zurück.
;
; Beispiel: Der kombinierte Flagwert '9' (1 + 8) überschreibt das Zielverzeichnis und prüft vorher, ob
; die Zielverzeichnisstruktur besteht und erstellt sie gegebenenfalls automatisch.
; =========================================================================================================
Func _SaveFileCopy($Parm_Src, $Parm_Dest, $Parm_Flag=0)
Local $Loc_Searchhandle, $Loc_SrcFilename
Local $Loc_SrcDrive, $Loc_SrcDir, $Loc_SrcName, $Loc_SrcExt
Local $Loc_RV=1 ; Standardrückgabe = ok, ein einzelner Fehler setzt Rückgabe auf 0
If BitAND($Parm_Flag, 1) = 1 then ; Zieldateien überschrieben?
; Wenn ja, dann Standard FileCopy() Funktion verwenden
FileCopy($Parm_Src, $Parm_Dest, $Parm_Flag)
Else ; Zieldateien nicht überschrieben
If ((StringInStr($Parm_Src,"*")>0) Or (StringInStr($Parm_Src,"?")>0)) Then
; Wildcard benutzt
; Dann alle möglichen Quelldateien bestimmen
$Loc_Searchhandle = FileFindFirstFile($Parm_Src)
; Prüfen, ob die Suche erfolgreich war
If ($Loc_Searchhandle = -1) Then ; Keine Datei entspricht Suchmuster in $Parm_Src
Return 0
else ; Mindestens eine Quelldatei entspricht Suchmuster in $Parm_Src
While 1 ; Endlosschleife
; ; Suche Namen einer passenden Quelldatei
$Loc_SrcFilename = FileFindNextFile($Loc_Searchhandle)
If @error Then ; bis alle Quelldateien überprüft
ExitLoop
else ; ansonsten kopiere Quelldatei
; FileFindNextFile findet nur den Dateinamen ohne Pfad
; deshalb ergänzen um Quelllaufwerk und Quellpfad
_PathSplit(_CompletePath($Parm_Src), $Loc_SrcDrive, $Loc_SrcDir, $Loc_SrcName, $Loc_SrcExt)
If (_SaveCopySingleFile($Loc_SrcDrive&$Loc_SrcDir&$Loc_SrcFilename, $Parm_Dest, $Parm_Flag)=0) then
$Loc_RV=0 ; und setzte Rückgabewert auf 0 ( = Fehler)
; wenn mindestens ein Fehler aufgetreten
EndIf
EndIf
WEnd ; Ende Schleife
FileClose($Loc_Searchhandle) ; Am Ende Handle für Suche wieder schliessen
Return ($Loc_RV)
EndIf
Else ; Keine Wildcards
Return (_SaveCopySingleFile($Parm_Src, $Parm_Dest, $Parm_Flag))
EndIf
EndIf ; Ende Zieldateien nicht überschrieben
EndFunc
; =========================================================================================================
; _SaveCopySingleFile($Parm_Src, $Parm_Dest, $Parm_Flag=0)
;
; Funktion: Kopiert eine einzelne Datei.
;
; $Parm_Src: Die Quelldatei (relativ oder vollem Pfad) - Wildcards werden nicht unterstützt.
;
; $Parm_Dest: Das Zielverzeichnis (mit abschliessenden Backslash) oder die Zieldatei.
;
; $Parm_Flag [optional]: Dieses Flag bestimmt, ob die Zieldatei überschrieben wird, falls sie schon besteht.
; $Parm_Flag kann eine Kombination der folgenden sein:
; 0 = (Standard) bestehende Dateie nicht überschreiben
; 1 = Überschreiben der bestehenden Datei
; 8 = Erstellt die Zielverzeichnisstruktur, falls diese nicht besteht.
;
; Bemerkung: Wenn Flag eine gerade Zahl ist und die Zieldatei schon existiert, wird der Zielname um ein
; ' (n)' vor der Dateierweiterung ergänzt (n = Zahl ab 2, wobei Zielname noch nicht existiert)
; analog zum Verhalten des Windows Explorers mit der Option 'beide Dateien behalten'.
;
; Rückgabe: Erfolg - Gibt 1 zurück.
; Fehlerfall - Gibt 0 zurück.
;
; Beispiel: Der kombinierte Flagwert '9' (1 + 8) überschreibt das Zielverzeichnis und prüft vorher, ob
; die Zielverzeichnisstruktur besteht und erstellt sie gegebenenfalls automatisch.
; =========================================================================================================
Func _SaveCopySingleFile($Parm_Src, $Parm_Dest, $Parm_Flag=0)
Local $Loc_FullDestFileName, $Loc_Count, $Loc_NewDest, $Loc_DestArray, $Loc_SrcArray
Local $Loc_DestDrive, $Loc_DestDir, $Loc_DestName, $Loc_DestExt
Local $Loc_SrcDrive, $Loc_SrcDir, $Loc_SrcName, $Loc_SrcExt
If BitAND($Parm_Flag, 1) = 1 then ; Zieldateien überschrieben?
; Wenn ja, dann Standard FileCopy() Funktion verwenden
FileCopy($Parm_Src, $Parm_Dest, $Parm_Flag)
Else ; Zieldatei nicht überschreiben
If Not ((StringInStr($Parm_Src,"*")>0) Or (StringInStr($Parm_Src,"?")>0)) Then
; No Wildcards
If StringRight(StringStripWS($Parm_Dest,2),1)="\" Then ; Ziel ist ein Verzeichnis
; dann Dateiname und Dateiextension für Zieldatei aus Quelle bestimmen
_PathSplit(_CompletePath($Parm_Dest), $Loc_DestDrive, $Loc_DestDir, $Loc_DestName, $Loc_DestExt)
_PathSplit($Parm_Src, $Loc_SrcDrive, $Loc_SrcDir, $Loc_SrcName, $Loc_SrcExt)
; Absoluter Zieldateiname ohne Extenstion = Ziellaufwerk + Zielverzeichnis + Quelldateiname
$Loc_FullDestFileName = $Loc_DestDrive & $Loc_DestDir & $Loc_SrcName
; Zieldateiextension = Quellextension
$Loc_DestExt=$Loc_SrcExt
Else ; Ziel ist eine Datei
; dann Dateiname und Dateiextension für Zieldatei aus Ziel bestimmen
$Loc_DestArray = _PathSplit(_CompletePath($Parm_Dest), $Loc_DestDrive, $Loc_DestDir, $Loc_DestName, $Loc_DestExt)
; Absoluter Zieldateiname ohne Extenstion = Ziellaufwerk + Zielverzeichnis + Zieldateiname
$Loc_FullDestFileName=$Loc_DestDrive & $Loc_DestDir & $Loc_DestName
EndIf ; Ende Ziel ist eine Datei
$Loc_Count=1 ; Analog zu Windows beim 1. Versuch 'Dateiname',
$Loc_NewDest=$Loc_FullDestFileName ; dann 'Dateiname (2)', ... usw. in $Loc_NewDest
While FileExists($Loc_NewDest&$Loc_DestExt) ; Durchlaufe Schleife bis Dateiname nicht existiert
$Loc_Count+=1 ; Zähler um 1 erhöhen
$Loc_NewDest = $Loc_FullDestFileName & " ("&$Loc_Count&")"
WEnd ; Ende Schleife
Return (FileCopy ($Parm_Src, $Loc_NewDest&$Loc_DestExt, $Parm_Flag))
Else ; Wildcards sind nicht erlaubt - also Rückgabewert 0
Return 0
EndIf ; Ende Wildcards
EndIf ; Ende Zieldatei nicht überschreiben
EndFunc
; =========================================================================================================
; Func _CompletePath($Parm_Path)
;
; Funktion: Ergänzt - falls notwendig - den angegebenen relativen Pfad zu einem absoluten Pfad
;
; $Parm_Path: Übergebener absoluter oder relativer Pfad
;
; Rückgabe: Zugehöriger absoluter Pfad
;
; =========================================================================================================
Func _CompletePath($Parm_Path)
If (StringLeft($Parm_Path,1)=".") Then ; Bei relativen Pfaden mit die mit '.'
; oder '..' beginnen
$Parm_Path=_PathFull($Parm_Path) ; Absoluter Pfad relativ zu Arbeitsverzeichnis
; berechnen
ElseIf not (StringInStr($Parm_Path,":")>0) then ; Bei Pfaden etwas ohne Laufwerkbuchstaben
if Not (StringLeft($Parm_Path,1)="\") then ; Pfade ohne beginnendes Backslash
$Parm_Path=_PathFull($Parm_Path) ; Absoluter Pfad relativ zu Arbeitsverzeichnis
; berechnen
Elseif Not (StringLeft($Parm_Path,2)="\\") then ; oder Pfade die EINEM Backslash beginnen
; (also keine UNC-Pfade)
$Parm_Path=StringLeft(@WorkingDir,2)&$Parm_Path ; Pfad um Laufwerk des Arbeitsverzeichnisses
; ergänzen
EndIf
EndIf ; Ende Pfad ohne Laufwerkbuchstaben
; (Bei UNC- oder absoluten Pfaden mit Laufwerksbuchstaben - Eingabe unverändert zurückgeben)
Return $Parm_Path
EndFunc
Alles anzeigen
Der Aufruf erfolgt mit _SaveFileCopy() mit exakt den gleichen Parametern wie das Standard Filecopy.
Die Routine berücksichtigt auch Jokersysmbole beim Dateinamen und wirkt wenn Flag=1 oder 9 als Wrapper für die normale FileCopy() Funktion. Ansonsten scheitert die Funktion nicht, wenn die Zieldatei schon vorhanden ist, sondern kopiert statt dessen nach "Dateiname (n).Extension" (n=2 oder größer falls eine Datei mit diesem Namen schon existiert).
Die Hilfsfunktion _SaveCopySingleFile() kopiert eine eine einzelne Datei und unterstützt keine Wildcards. Die Funktion wird für den Kopiervorgang einer einzelnen Datei von _SaveFileCopy() aufgerufen.
Die Hilfsfunktion _CompletePath() ist ein Wrapper für _PathFull() aus der File.au3 UDF. Im Gegensatz zu _PathFull() muß hier der übergegeben Parameter kein relativer Pfad sein. Man muß keine Fallunterscheidungen beim Parameter mehr machen, sondern man erhält von der Funktion immer einen absolut adressierten Pfad.
Übergebene Pfade die von der Root adressieren - aber ohne Laufwerksbuchstaben - werden um den Laufwerkbuchstaben des WorkingDirectories ergänzt. Übergebene absolute Pfade mit Laufwerkbuchstaben oder in UNC-Notation werden nicht ergänzt.
Peter