Klingt zwar ganz gut, aber wie kopiert man mit der Funktion ganze Ornder (die Ordnerstruktur soll erhalten bleiben!) ??
mfg
Leo.1906
Klingt zwar ganz gut, aber wie kopiert man mit der Funktion ganze Ornder (die Ordnerstruktur soll erhalten bleiben!) ??
mfg
Leo.1906
Hallo Oscar.
Läuft super.
Geht das auch incl. Unterverzeichnisse?
LG,
Crazy-A.
@Crazy-A
Hast du verstanden, wie man Ordner kopiert?
(hört sich nämlich so an^^)
mfg
Leo.1906
Ganze Verzeichnisse (inkl. Unterverzeichnisse) mit Erhalt der Struktur geht (noch) nicht!
Ich bin aber schon dabei...
So, jetzt kann man damit auch ganze Verzeichnisse (rekursiv) kopieren. Die Verzeichnisstruktur wird vom Quellverzeichnis übernommen und im Zielverzeichnis erstellt.
Alle zufriedengestellt?
Hi
erstmal: Sehr genial, meine Hochachtung!
hab einen (möglichen) Bug entdeckt:
Zeile 77: $sNewFolder = StringReplace(StringReplace($aSource[$i], $sFile, ''), $sSourcePath, '')
Ein Ordner kann durchaus zb "Test.zip" heißen. Wenn nun eine Datei in diesem Ornder auch "Test.zip" heißt, dann wird auch der Ordner replaced!
Deshalb hab ich die Zeile 77 auf folgende geändert:
$sNewFolder = StringTrimLeft(StringLeft($aSource[$i],StringInStr($aSource[$i],"\",0,-1)),StringLen($sSourcePath))
weiters hab ich mir erlaubt einen weiteren Parameter hinzuzufügen:
_MultiFileCopy($aSource, $sDestPath, $bOverWrite = True, $sPreFix = "Copy")
Wenn $bOverWrite=False, dann wird die ZielDatei, falls sie existiert, nicht überschrieben, sondern mit dem Prefix umbenannt ("Text.txt" wird zu "Copy1_Text.txt")
Falls auch die "Copy1_Text.txt" schon existiert, dann "Copy2_Text.txt"
und die Zieldateien werden als Array zurückgegeben
Ich brauchte das so für ein Projekt von mir...
Script 2 mal laufen lassen, dann sollten die Dateien der 2 Demo (Zeile 28 ) umbenannt werden!
;===werden benötigt=============================================================
#include<String.au3>
#include<WindowsConstants.au3>
#include<Misc.au3>
;===============================================================================
;===Beispiel 1 (komplettes Verzeichnis kopieren)================================
; Alle Dateien und Unterverzeichnisse (rekursiv) werden kopiert
; Verzeichnisstruktur der Quelle wird übernommen
Global $sSourcePath = 'C:\Programme\AutoIt3\AutoitX'
Global $sDestinationPath = @ScriptDir & '\Tmp1'; Zielpfad (wird ggf. erstellt)
$Ret=_MultiFileCopy($sSourcePath, $sDestinationPath)
For $i= 1 to $Ret[0]
MsgBox(0, "Dateien überschreiben", $i & " / " & $Ret[0] & @CRLF & $Ret[$i])
Next
;===============================================================================
;===Beispiel 2 (mehrere Dateien kopieren)=======================================
; Alle Dateien aus dem Array werden ins Zielverzeichnis kopiert
; Array[0] muss die Anzahl der zu kopierenden Dateien enthalten
Global $aSource[4] = [3, @SystemDir & '\shell32.dll', @SystemDir & '\mspaint.exe', @SystemDir & '\eula.txt']
Global $sDestinationPath = @ScriptDir & '\Tmp2'; Zielpfad (wird ggf. erstellt)
$Ret=_MultiFileCopy($aSource, $sDestinationPath, False)
For $i= 1 to $Ret[0]
MsgBox(0,"Vorhandene Dateien umbenennen", $i & " / " & $Ret[0] & @CRLF & $Ret[$i])
Next
;===============================================================================
;===============================================================================
;
; Function Name: _MultiFileCopy
; Description:: Kopiert mehrere Dateien mit Progressbar
; Parameter(s): Array mit Dateien zum kopieren, Zielpfad
; Requirement(s):
; #include<String.au3>
; #include<WindowsConstants.au3>
; #include<Misc.au3>
; Author(s): Tom99, progandy and Oscar (http://www.autoit.de)
;
;===============================================================================
;
Func _MultiFileCopy($aSource, $sDestPath, $bOverWrite = True, $sPreFix = "Copy")
Local $opt = Opt('GUICloseOnESC', 0), $ret, $sShowSource, $sShowDest, $sSourcePath = '', $sNewFolder = '', $i, $j, $k
Local $aMFC[12] = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, False, DllOpen('user32.dll')]
If Not IsArray($aSource) Then
$sSourcePath = $aSource
If StringRight($sSourcePath, 1) <> '\' Then $sSourcePath &= '\'
ToolTip('Bitte warten! Verzeichnis wird eingelesen!')
$aSource = _GetFilesFolder_Rekursiv($aSource, '*', 0)
ToolTip('')
Else
If Not IsNumber($aSource[0]) Then Return SetError(1, 0, 0)
EndIf
Local $aReturn = $aSource
If StringRight($sDestPath, 1) <> '\' Then $sDestPath &= '\'
If Not FileExists($sDestPath) Then
If Not DirCreate($sDestPath) Then Return SetError(2, 0, 0)
EndIf
$sShowDest = StringRegExpReplace($sDestPath, '(.{15})(.*)(.{35})', '$1' & '[...]' & '$3')
Local $aFileSize[UBound($aSource)]
For $i = 1 To $aSource[0]
$aFileSize[$i] = FileGetSize($aSource[$i])
$aMFC[7] += $aFileSize[$i]
Next
Local $callback = DllCallbackRegister('__Progress', 'int', 'uint64;uint64;uint64;uint64;dword;dword;ptr;ptr;str')
Local $ptr = DllCallbackGetPtr($callback)
__ProgressCreate($aMFC)
$aMFC[9] = TimerInit()
For $i = 1 To $aSource[0]
$sArray = ''
For $j = 0 To 11
$sArray &= $aMFC[$j] & ';'
Next
If $sSourcePath <> '' Then
$sNewFolder = StringTrimLeft(StringLeft($aSource[$i],StringInStr($aSource[$i],"\",0,-1)),StringLen($sSourcePath))
If Not FileExists($sDestPath & $sNewFolder) Then
If Not DirCreate($sDestPath & $sNewFolder) Then Return SetError(3, 0, 0)
EndIf
EndIf
$sFile = StringMid($aSource[$i], StringInStr($aSource[$i], '\', 0, -1) + 1)
$k = 0
While $bOverWrite=False And FileExists($sDestPath & $sNewFolder & $sFile)
$k+=1
$sFile=$sPreFix & $k & "_" & StringMid($aSource[$i], StringInStr($aSource[$i], '\', 0, -1) + 1)
WEnd
$sShowSource = StringRegExpReplace($aSource[$i], '(.{15})(.*)(.{35})', '$1' & '[...]' & '$3')
GUICtrlSetData($aMFC[1], 'Kopiere Datei ' & @CRLF & '"' & $sShowSource & '"' & @CRLF & 'nach: "' & $sShowDest & '"')
$ret = DllCall('kernel32.dll', 'int', 'CopyFileExA', 'str', $aSource[$i], 'str', $sDestPath & $sNewFolder & $sFile, 'ptr', $ptr, 'str', $sArray, 'int', 0, 'int', 0)
$aReturn[$i] = $sDestPath & $sNewFolder & $sFile
;~ ConsoleWrite('Return: ' & $ret[0] & @LF)
If $ret[0] = 0 Then $aMFC[10] = True
$aMFC[8] += $aFileSize[$i]
Next
GUIDelete($aMFC[0])
DllClose($aMFC[11])
Opt('GUICloseOnESC', $opt)
Return $aReturn
EndFunc ;==>_MultiFileCopy
Func __ProgressCreate(ByRef $aMFC)
$aMFC[0] = GUICreate('FileCopy', 480, 220, -1, -1, $WS_POPUPWINDOW)
$aMFC[1] = GUICtrlCreateLabel('', 10, 10, 460, 65)
GUICtrlSetFont(-1, 10, 400, 0, 'Courier New')
GUICtrlCreateLabel('Datei:', 10, 83, 60, 16)
GUICtrlSetFont(-1, 11, 600, 0, 'Courier New')
$aMFC[2] = GUICtrlCreateLabel('0 %', 80, 83, 390, 16)
GUICtrlSetFont(-1, 11, 600, 0, 'Courier New')
$aMFC[4] = GUICtrlCreateProgress(10, 100, 460, 20)
GUICtrlCreateLabel('Gesamt:', 10, 133, 60, 16)
GUICtrlSetFont(-1, 11, 600, 0, 'Courier New')
$aMFC[3] = GUICtrlCreateLabel('0 %', 80, 133, 390, 16)
GUICtrlSetFont(-1, 11, 600, 0, 'Courier New')
$aMFC[5] = GUICtrlCreateProgress(10, 150, 460, 20)
$aMFC[6] = GUICtrlCreateButton('Abbrechen', 200, 185, 75, 25)
GUICtrlSetFont(-1, 9, 400, 0, 'Arial')
GUISetState()
Sleep(200)
EndFunc ;==>__ProgressCreate
Func __Progress($FileSize, $BytesTransferred, $StreamSize, $StreamBytesTransferred, $dwStreamNumber, $dwCallbackReason, $hSourceFile, $hDestinationFile, $lpData)
Local $aSplit = StringSplit(StringTrimRight($lpData, 1), ";")
If $aSplit[11] = 'True' Then Return 1
Local $pos = GUIGetCursorInfo($aSplit[1])
If _IsPressed('1B', Int($aSplit[12])) Then Return 1
If _IsPressed('01', Int($aSplit[12])) And ($pos[4] = Int($aSplit[7])) Then Return 1
Local $sPercent = Round($BytesTransferred / $FileSize * 100, 0), $iTime, $iTotalTime, $iTransferRate
Local $sPercentAll = Round(($aSplit[9] + $BytesTransferred) / $aSplit[8] * 100, 0)
If GUICtrlRead($aSplit[5]) <> $sPercent Then
$iTime = TimerDiff($aSplit[10])
$iTotalTime = Ceiling($iTime / 1000 / ($sPercentAll + 0.1) * 100)
$iTransferRate = _StringAddThousandsSep(Int($aSplit[8] / $iTotalTime / 1000), '.', ',')
GUICtrlSetData($aSplit[3], $sPercent & ' %')
GUICtrlSetData($aSplit[5], $sPercent)
If GUICtrlRead($aSplit[6]) <> $sPercentAll Then
GUICtrlSetData($aSplit[4], $sPercentAll & ' % Zeit: ' & Int($iTime / 1000) & '/' & $iTotalTime & ' s (' & $iTransferRate & ' KB/s)')
GUICtrlSetData($aSplit[6], $sPercentAll)
EndIf
EndIf
EndFunc ;==>__Progress
;==================================================================================================
; Function Name: _GetFilesFolder_Rekursiv($sPath [, $sExt='*' [, $iDir=-1 [, $iRetType=0 ,[$sDelim='0']]]])
; Description: Rekursive Auflistung von Dateien und/oder Ordnern
; Parameter(s): $sPath der Basispfad für die Auflistung ('.' -aktueller Pfad, '..' -Parentpfad)
; $sExt Erweiterung für Dateiauswahl '*' oder -1 für alle (Standard)
; $iDir -1 Dateien+Ordner(Standard), 0 nur Dateien, 1 nur Ordner
; optional: $iRetType 0 gibt Array, 1 gibt String zurück
; optional: $sDelim legt Trennzeichen für Stringrückgabe fest
; 0 -@CRLF (Standard) 1 -@CR 2 -@LF 3 -';' 4 -'|'
; Return Value(s): Array (Standard) od. String mit den gefundenen Pfaden der Dateien und/oder Ordner
; Array[0] enthält die Anzahl der gefundenen Dateien/Ordner
; Author(s): BugFix ([email='bugfix@autoit.de'][/email])
;==================================================================================================
Func _GetFilesFolder_Rekursiv($sPath, $sExt='*', $iDir=-1, $iRetType=0, $sDelim='0')
Global $oFSO = ObjCreate('Scripting.FileSystemObject')
Global $strFiles = ''
Switch $sDelim
Case '1'
$sDelim = @CR
Case '2'
$sDelim = @LF
Case '3'
$sDelim = ';'
Case '4'
$sDelim = '|'
Case Else
$sDelim = @CRLF
EndSwitch
If ($iRetType < 0) Or ($iRetType > 1) Then $iRetType = 0
If $sExt = -1 Then $sExt = '*'
If ($iDir < -1) Or ($iDir > 1) Then $iDir = -1
_ShowSubFolders($oFSO.GetFolder($sPath),$sExt,$iDir,$sDelim)
If $iRetType = 0 Then
Local $aOut
$aOut = StringSplit(StringTrimRight($strFiles, StringLen($sDelim)), $sDelim, 1)
If $aOut[1] = '' Then
ReDim $aOut[1]
$aOut[0] = 0
EndIf
Return $aOut
Else
Return StringTrimRight($strFiles, StringLen($sDelim))
EndIf
EndFunc
Func _ShowSubFolders($Folder, $Ext='*', $Dir=-1, $Delim=@CRLF)
If Not IsDeclared("strFiles") Then Global $strFiles = ''
If ($Dir = -1) Or ($Dir = 0) Then
For $file In $Folder.Files
If $Ext <> '*' Then
If StringRight($file.Name, StringLen($Ext)) = $Ext Then _
$strFiles &= $file.Path & $Delim
Else
$strFiles &= $file.Path & $Delim
EndIf
Next
EndIf
For $Subfolder In $Folder.SubFolders
If ($Dir = -1) Or ($Dir = 1) Then $strFiles &= $Subfolder.Path & '\' & $Delim
_ShowSubFolders($Subfolder, $Ext, $Dir, $Delim)
Next
EndFunc
Außerdem hab ich die Variablen $i und $j in der Funktion deklariert, da es sonst zu Problemen kommen kann, wenn man die Funktion in einer $i-Schleife aufruft...
lgE
Außerdem hab ich die Variablen $i und $j in der Funktion deklariert, da es sonst zu Problemen kommen kann, wenn man die Funktion in einer $i-Schleife aufruft...
Das kann nicht passieren, $i und $j sind Variablen in For-Schleifen. Diese werden per default als Local deklariert.
@BufIx: Oh, das wußte ich nicht...Danke für die Info!
Der PreFix sollte natürlich auch noch auf seine Regularität überprüft werden, damit man keine unerlaubten Sonderzeichen verwenden kann...
lgE
eukalyptus: Oh mann, da habe ich ja einen Schnitzer mit dem StringReplace gemacht.
Deine Änderungen habe ich mal so übernommen (im Post #1 gibt es die neue Version).
Finde ich klasse, was aus so einer Funktion werden kann, wenn einige User zusammenarbeiten.
Es gibt nochmal eine neue Version (siehe Post #1). Habe noch zwei kleine Bugs beseitigt!
Ciao! nicht schlecht das Ganze
könnte man das Fenster so kreieren, dass der User das auch minimieren kann ?
Bei mir tritt der Fehler auf, wenn ich ein Fenster (während dem Kopieren) auf die MultiFileCopy Anwendung schiebe..
und alles wieder minimiere, und dann wieder zurück schiebe..das MultiFileCopy dann wie hängt (grafik) mässig kommt es nicht mehr mit, könnte man das anders lösen? was ist Schuld? die GUI Komponente von Autoit?
greet;s satinez
Wenn Du in der Zeile:
[autoit]$aMFC[0] = GUICreate('FileCopy', 480, 220, -1, -1, $WS_POPUPWINDOW)
[/autoit]hinten das ", $WS_POPUPWINDOW" löschst, dann kannst Du das Fenster auch verschieben/minimieren.
ok, danke!
Ist das jetzt nur bei mir, oder kann ich es nicht immer verschieben?
Ich kann das nicht nachvollziehen. Ich kann das Fenster verschieben, während das Programm Dateien kopiert.
Beschreibe doch mal genauer, was Du kopierst und was Du dann machst oder machen willst, was nicht funktioniert.
Bei mir friert das Fenster immer ein ich weiss nicht warum.
Er kopiert ein Teil der Daten dann zeigt das Fenster nichts mehr an und es steht (Keine Rückmeldung).
Dann kann ich es nicht verschieben und Abbrechen funzt auch nicht mehr
Mache ich da was falsch? Die Dateien die er kopieren soll, kommen von einer Netzwerkfreigabe
was eigentlich kein Problem sein sollte.
Danke, auch wenn ich aufdringlich bin, ich finde dieses Script sehr nützlich und würde es gerne weiterhin gebrauchen
Netzwerkfreigabe! Habe ich gerade mal getestet. Das stimmt!
Dabei gibt es ein Problem: Das Script kopiert zwar im Hintergrund weiter, aber das Fenster wird nach kurzer Zeit nicht mehr refresht (siehe Screenshot).
Wobei das nur beim kopieren über's Netz passiert (egal ob Laufwerksbuchstabe oder Pfad und egal ob Quelle oder Ziel).
Screenshot:
AutoItImage.GIF
Vielleicht kann sich das einer unserer DLL-Profis mal ansehen?
Liegt denn das wirklich an der DLL ?
hmmm..gibts denn da ne möglichkeit, den windows normalen kopier-dialog zu verwenden ?
Wobei das nur beim kopieren über's Netz passiert (egal ob Laufwerksbuchstabe oder Pfad und egal ob Quelle oder Ziel).
Ich denke, das ist ein reines Windows-Problem. Wenn ich per Explorer ins Netz kopiere, funktioniert die Fortschrittsanzeige auch nur bedingt, d.h. die Statusbar arbeitet rein nach Anzahl der Dateien (z.B. 2 Dateien - je 50% Statusbar) und zeigt diesen 'Fortschritt' bei Beginn des Kopiervorgangs für diese Datei an. Ist die letzte Datei eine größere, hast du ewig eine 100% - Anzeige.
BugFix : Kann ich nicht nachvollziehen. Bei mir funktioniert die Anzeige beim kopieren mit dem Explorer ganz normal (vom Netzwerklaufwerk auf's Lokale Laufwerk und umgekehrt). Habe ich gerade mal getestet, weil ich ja sonst immer den TotalCommander dafür benutze.
Ich hab auch schon versuchsweise, die Zeilen zum Abbrechen aus meinem Script entfernt, aber das Problem bleibt.
Kann ich nicht nachvollziehen.
Man was ist das Windows doch für 'ne tolle Sache: Du hast eines, ich hab eines - aber trotzdem macht jedes was es will.