Files in verschiedenen Ordnern mit einem bestimmten Datum auslesen, moven und Ordnerstruktur herstellen

  • Hallo Freundinnen und Freunde,

    für euch wird es vermutlich ein "Klacks" sein, für mich stellt es eine Hürde da:

    Ich muss von einem Netz-Laufwerk den Inhalt zahlreicher Ordner auslesen, jene Files von einem bestimmten Datum ABWÄRTS auslesen und in einen neuen Ordner mit der gesamten vorherigen Ordner-Struktur mit den ausgewählten Files wieder herstellen.

    Offenbar verrenne ich mich (bin noch ziemlich neu in AutoIT), weshalb mit Sicherheit auch meine bisherigen Versuche keinen interessieren. Mein Ansatz war, die Verzeichnisse rekursiv in ein Array auszulesen und die erforderlichen Files zu filtern. Das hat einigermaßen funktioniert. Nur das Erstellen innerhalb des selben Netz-Laufwerkes mit dem Aufbau der Ordnerstruktur in einem eigenen Verzeichnis und das Verschieben der Files dorthin bereitet mir unheimliche Probleme.

    Ich habe bereits versucht, im Forum etwas Ähnliches zu suchen, habe jedoch nichts gefunden.

    Hat vielleicht jemand eine Lösung ?????


    Bin euch allen sehr dankbar

    lg

    Steve

  • Das geht im Prinzip sehr leicht :)
    Kleines Beispiel:

    [autoit]

    $Von = "\\Server1\Share1$"
    $Nach = "\\Server5\Share2$"
    $Datei = "\\Server1\Share1$\Verzeichnis\Unterverzeichnis\Datei"
    $Zieldatei = StringReplace($Datei, $Von, $Nach)
    FileCopy($Datei, $Zieldatei, 8); FLAG 8 ist wichtig ;)

    [/autoit]
  • Danke dir vorerst für deinen Ansatz.

    Das Problem liegt jedoch darin, dass alles Jahresbezogen und rekursiv für die Untervzeichnisse abgearbeitet werden muss. Die Applikation sollte so aussehen:

    Ermittle alle Files im Netz-Unterverzeichnis, die das Datum 2002 und früher haben - bilde die Untervzeichnisse nach und verschiebe alle Files, die dem Profil entsprechen wieder in die neu zu gestaltenden Unterverzeichnisse. Sollte ein Unterverzeichnis leer sein, sollte dieses gelöscht werden.

    Danke nochmals für eure Bemühungen ;)

    Steve

    Einmal editiert, zuletzt von mr_merlin (31. Oktober 2013 um 09:07)

  • Achso ich dachte es scheitert nur an der Ordnerstruktur. Weil du geschrieben hattest es bereitet dir unheimliche Probleme
    Du könntest wie folgt vorgehen:

    [autoit]


    $aDaten ; Daten von Quellpfad einlesen z.B. mit _GetFilesFolder_Rekursiv()
    for $i = 1 to $aDaten[0]
    If FileGetTime ...; prüfen ob daten älter als 2002
    Filemove; wenn älter dann verschieben
    endif
    next

    [/autoit]
  • Hallo Schnitzel,

    Habe versucht, mit dem Script von bernd670, FilesListRecursive, ein Array zu bilden. Leider wird das Array nur mit den Ordnern, nicht jedoch mit den Files angezeigt. Was mache ich da nur falsch?


    Spoiler anzeigen
    [autoit]


    #include <Array.au3>
    #include <date.au3>
    #include <file.au3>
    $Verzeichnis='P:\'
    $erg=FileListRecursive($Verzeichnis,'*.*',0,1)
    _ArrayDisplay($erg)
    ;===============================================================================
    ; Name: FileListRecursive
    ; Description: Sucht rekursiv nach Dateien und Ordnern
    ; Parameter(s): $szStartPath = Path ab dem gesucht werden soll
    ; $szFileName = Datei nach der gesucht werden soll
    ; $iFlag (optional) = Gibt an was zurückgegeben werden soll
    ; 0 = Dateien und Ordner (default)
    ; 1 = nur Dateien
    ; 2 = nur Ordner (ignoriert $szFileName)
    ; $iRetFormat (optional) = Rückgabeformat
    ; 0 = als String (default)
    ; 1 = als Array
    ; $szDelim (optional) = Trennzeichen wenn $iRetFormat = 0 (@CRLF ist default)
    ; Requirement(s): keine
    ; Return Value(s): bei Erfolg: Ergebnis als String oder Array
    ; bei Fehler:
    ; Author(s): bernd670
    ;
    ;===============================================================================
    Func FileListRecursive($szStartPath, $szFileName, $iFlag = 0, $iRetFormat = 0, $szDelim = @CRLF)
    Local $hFF, $szFindName, $szRetValue = ""
    If $iFlag = Default Then $iFlag = 0
    If $iRetFormat = Default Then $iRetFormat = 0
    If $szDelim = Default Then $szDelim = @CRLF
    If StringRight($szStartPath, 1) <> "" Then $szStartPath &= ""
    If $iFlag < 2 Then
    $hFF = FileFindFirstFile($szStartPath & $szFileName)
    If $hFF <> -1 Then
    While True
    $szFindName = FileFindNextFile($hFF)
    If @error Then
    FileClose($hFF)
    ExitLoop
    EndIf
    If ($szRetValue <> "") And (StringRight($szRetValue, StringLen($szDelim)) <> $szDelim) Then $szRetValue &= $szDelim
    $szRetValue &= $szStartPath & $szFindName
    WEnd
    EndIf
    EndIf
    $hFF = FileFindFirstFile($szStartPath & "*.*")
    If $hFF = -1 Then Return $szRetValue
    While True
    $szFindName = FileFindNextFile($hFF)
    If @error Then
    FileClose($hFF)
    ExitLoop
    EndIf
    If StringInStr(FileGetAttrib($szStartPath & $szFindName), "d") Then
    If ($szRetValue <> "") And (StringRight($szRetValue, StringLen($szDelim)) <> $szDelim) Then $szRetValue &= $szDelim
    If ($iFlag = 0) Or ($iFlag = 2) Then $szRetValue &= $szStartPath & $szFindName & "" & $szDelim
    $szRetValue &= FileListRecursive($szStartPath & $szFindName & "", $szFileName, $iFlag, 0, $szDelim)
    EndIf
    WEnd
    If StringRight($szRetValue, StringLen($szDelim)) = $szDelim Then $szRetValue = StringTrimRight($szRetValue, StringLen($szDelim))
    If $iRetFormat = 0 Then
    Return $szRetValue
    Else
    Return StringSplit($szRetValue, $szDelim, 1)
    EndIf
    EndFunc ;==>FileListRecursive

    [/autoit]
  • In der neuen Autoit Beta v3.3.9.21 hat es eine sehr nützliche funktion mit der so etwas einfach umzusetzen ist ich hab mal ein kleines beispiel gemacht
    aber Achtung man kann damit schnell seinen Speicher zumüllen

    die Funktion macht im prinzip das gleiche wie deine Funktion aber sie sucht nur nach Dateien und nicht nach Ordnern da die ja im Dateipfad "stecken"
    filecopy erstellt dann das verzeichnis neu(an anderer stelle) wen es nicht existiert.

    Spoiler anzeigen
    [autoit]

    #include <File.au3>
    $datum=InputBox("Datum" ,"Format JJJJMMTTHHMMSS"&@CRLF&"Dateien die neuer als XXXX sind werden kopiert" ,"20130130000000")
    $foldersource=FileSelectFolder("Auswahl source" ,@DesktopDir);quelle
    $folderdest=FileSelectFolder("Auswahl destination" ,@DesktopDir);ziel
    if MsgBox(52,"ACHTUNG" ,"ACHTUNG!! es können große Datenmengen bewegt werden"&@CRLF&"Weiter?")=7 Then Exit
    $filearray=_FileListToArrayRec($foldersource ,"*" ,1 ,1 ,0 ,1);AutoIt Beta funktion V3.3.9.21
    For $i1=1 to $filearray[0];schleife index 0 enthält anzahl
    If FileGetTime($filearray[$i1] ,1 ,1)>$datum then;wenn File datum Größer gesuchtem datum
    $copy=FileCopy($foldersource&""&$filearray[$i1] ,$folderdest&""&$filearray[$i1],8)
    ;erstellt verzeichnis fals nicht vorhanden und kopiert die Dateien
    If $copy=0 Then ExitLoop;falls ein fehler auftritt
    EndIf
    Next

    [/autoit]
  • Habe deine Funktion mit der Beta 3.3.9.21 versucht. Leider tut sich gelinde gesagt gar nichts. Nach 101 Sekunden endet das Programm ordnungsgemäß, hat jedoch nichts getan!

    Ich habe ein Laufwerk P:\ dessen Verzeichnisse UND Unterverzeichnisse nach Files durchsucht werden sollen, die älter als 31.12.2006 sind. Diese sollten dann mit der Verzeichnisstruktur nach C:\Temp\ verschoben werden. Toll wäre es auch, wenn durch das Verschieben leere Unterverzeichnisse entstehen (auf P:\), dies auch gelöscht werden. Dies ist aber sekundär.

    Danke nochmals für euer Bemühen!

    lg


    Merlin

  • Vermutlich ist da einiges falsch "rübergekommen". Vorerst möchte ich mich bei allen bedanken, die einen Lösungsansatz gepostet haben. Ich möchte wirklich kein fertiges Programm, obwohl mir OSKAR bei meinen ersten Probleben mit AutoIT bereits vieles fix- und fertig geliefert hat. Vermutlich bin ich zu dumm und brauche offensichtlich Lösungsansätze. Den Rest kann ich hoffentlich selbst erstellen.

    Nichts für ungut an alle.

    Werde mich in Zukunft zurückhalten.

    LG


    Merlin

    • Offizieller Beitrag

    Dein Problem ist für einen Anfänger nicht ganz leicht zu lösen. Man muss schon genau wissen, was man für Pfade (relativ oder absolut) von der Einlesefunktion zurückbekommt.
    Dementsprechend muss man FileMove anpassen. Hier mal eine Fix- und Fertig-Version (zum testen kannst Du Zeile 20 auskommentieren):

    Spoiler anzeigen
    [autoit]


    Global $sDate = _InputDateBox(0, 'Kopier-Datum')
    If @error Then Exit ; Wenn der Benutzer auf Abbrechen geklickt hat, Programm beenden

    [/autoit] [autoit][/autoit] [autoit]

    Global $sSourceDir = FileSelectFolder('Quellverzeichnis auswählen!', '', 2, @ScriptDir) ; Quellverzeichnis auswählen!
    If @error Then Exit ; Wenn der Benutzer auf Abbrechen geklickt hat, Programm beenden
    If Not FileExists($sSourceDir) Then Exit MsgBox(0, 'Fehler!', 'Quellverzeichnis existiert nicht!')
    If StringRight($sSourceDir, 1) <> '\' Then $sSourceDir &= '\' ; Wenn am Ende des Verzeichnisses ein Backslash fehlt, diesen hinzufügen

    [/autoit] [autoit][/autoit] [autoit]

    Global $sDestDir = FileSelectFolder('Zielverzeichnis auswählen!', '', 2, @DesktopDir) ; Zielverzeichnis auswählen!
    If @error Then Exit ; Wenn der Benutzer auf Abbrechen geklickt hat, Programm beenden
    If Not FileExists($sDestDir) Then Exit MsgBox(0, 'Fehler!', 'Zielverzeichnis existiert nicht!')
    If StringRight($sDestDir, 1) <> '\' Then $sDestDir &= '\' ; Wenn am Ende des Verzeichnisses ein Backslash fehlt, diesen hinzufügen

    [/autoit] [autoit][/autoit] [autoit]

    Global $aFileList = _RecursiveFileListToArray($sSourceDir, '.*', 1) ; Alle Dateien aus dem Quellverzeichnis (rekursiv) einlesen
    ;~ _ArrayDisplay($aFileList)
    If MsgBox(4 + 48 + 256 + 262144, 'Sicherheitsfrage', 'Sollen die Dateien wirklich verschoben werden?') = 7 Then Exit
    For $i = 1 To $aFileList[0] ; $aFileList[0] enthält anzahl
    If FileGetTime($aFileList[$i], 0, 1) < $sDate Then ; wenn das Änderungsdatum der Datei kleiner als das ausgewählte Datum ist, dann Datei verschieben
    ConsoleWrite(StringFormat('\nQuelle: "%s"\n-> Ziel: "%s"\n', $aFileList[$i], StringReplace($aFileList[$i], $sSourceDir, $sDestDir)))
    If FileMove($aFileList[$i], StringReplace($aFileList[$i], $sSourceDir, $sDestDir), 8) = 0 Then ConsoleWrite('! Fehler! Die Datei konnte nicht verschoben werden!' & @CR & @CR)
    EndIf
    Next

    [/autoit] [autoit][/autoit] [autoit]

    ;===============================================================================
    ; Function Name: _InputDateBox([$iFormat][, $sTitle][, $sText][, $sDefaultDate][, $hParent])
    ; Description: Fragt den Benutzer nach Datum oder Datum und Uhrzeit und gibt dies als String in Form von "YYYYMMDDhhmmss" zurück
    ; Parameter(s): $iFormat = 0 oder 1
    ; bei 0 wird nur nach dem Datum gefragt (Uhrzeit wird dann als "000000" zurückgegeben)
    ; bei 1 wird nach Datum und Uhrzeit gefragt
    ; Requirement: -
    ; Return Value(s): bei Erfolg = String in Form von "YYYYMMDDhhmmss"
    ; bei Abbruch = Leerstring und @error = 1
    ; Author(s): Oscar (http://www.autoit.de)
    ;===============================================================================
    Func _InputDateBox($iFormat = 1, $sTitle = '', $sText = '', $sDefaultDate = '', $hParent = '')
    If $iFormat < 0 Or $iFormat > 1 Then $iFormat = 1
    If $sTitle = '' Or $sTitle = Default Then $sTitle = 'Datum-Box'
    If $sText = '' Or $sText = Default Then $sText = 'Bitte Datum auswählen!'
    If $iFormat Then $sText = 'Bitte Datum und Uhrzeit auswählen!'
    Local $iOnEventMode = Opt('GUIOnEventMode', 0), $sRetDate = '', $iError = 0
    Local $hGui = GUICreate($sTitle, 260 + $iFormat * 85, 130, Default, Default, Default, 8, $hParent)
    GUISetBkColor(0xCCCCCC, $hGui)
    GUISetIcon('shell32.dll', 24, $hGui)
    GUICtrlCreateGroup($sText, 10, 20, 240 + $iFormat * 85, 70)
    GUICtrlSetFont(-1, 10, 400, 0, 'Arial', 5)
    GUICtrlCreateIcon('shell32.dll', -21, 30, 48, 32, 32)
    Local $idDate = GUICtrlCreateDate($sDefaultDate, 75, 49, 150 + $iFormat * 85, 30, $iFormat)
    GUICtrlSetFont(-1, 14, 400, 0, 'Verdana', 5)
    If $iFormat Then
    Local $DTM_SETFORMAT_ = 0x1032
    Local $sStyle = 'dd.MM.yyyy HH:mm:ss'
    GUICtrlSendMsg($idDate, $DTM_SETFORMAT_, 0, $sStyle)
    EndIf
    GUICtrlCreateGroup('', -99, -99, 1, 1)
    Local $idOk = GUICtrlCreateButton('Ok', 100 + $iFormat * 85, 100, 60, 25, 1) ; <- Value 1 = $BS_DEFPUSHBUTTON
    Local $idCancel = GUICtrlCreateButton('Abbrechen', 170 + $iFormat * 85, 100, 80, 25)
    GUISetState(@SW_SHOW, $hGui)
    While True
    Switch GUIGetMsg()
    Case $idCancel, -3 ; <- Value -3 = $GUI_EVENT_CLOSE
    $iError = 1
    ExitLoop
    Case $idOk
    $sRetDate = StringRegExpReplace(GUICtrlRead($idDate), '(\d{2})\.(\d{2})\.(\d{4}).*', '$3$2$1')
    If $iFormat Then
    $sRetDate &= StringRegExpReplace(GUICtrlRead($idDate), '\d{2}\.\d{2}\.\d{4} (\d{2}):(\d{2}):(\d{2})', '$1$2$3')
    Else
    $sRetDate &= '000000'
    EndIf
    ExitLoop
    EndSwitch
    WEnd
    GUIDelete($hGui)
    Opt('GUIOnEventMode', $iOnEventMode)
    Return SetError($iError, 0, $sRetDate)
    EndFunc ;==>_InputDateBox

    [/autoit] [autoit][/autoit] [autoit]

    ;===============================================================================
    ; Function Name: _RecursiveFileListToArray($sPath[, $sPattern][, $iFlag][, $iFormat][, $fRecursion][, $sDelim])
    ; Description:: gibt Verzeichnisse (rekursiv) und/oder Dateien zurück, die einem RegExp-Pattern entsprechen
    ; Parameter(s): $sPath = Startverzeichnis
    ; $sPattern = ein beliebiges RexExp-Pattern für die Auswahl
    ; $iFlag = Auswahl
    ; 0 = Dateien & Verzeichnisse
    ; 1 = nur Dateien
    ; 2 = nur Verzeichnisse
    ; $iFormat = Rückgabeformat
    ; 0 = String
    ; 1 = Array mit [0] = Anzahl
    ; 2 = Nullbasiertes Array
    ; $fRecursion = Verzeichnisse rekursiv durchsuchen
    ; False = Nein
    ; True = Ja
    ; $sDelim = Trennzeichen für die String-Rückgabe
    ; Requirement(s): AutoIt 3.3.0.0
    ; Return Value(s): Array/String mit den gefundenen Dateien/Verzeichnissen
    ; Author(s): Oscar (http://www.autoit.de)
    ; Anregungen von: bernd670 (http://www.autoit.de)
    ; und: AspirinJunkie (http://www.autoit.de)
    ;===============================================================================
    Func _RecursiveFileListToArray($sPath, $sPattern = '', $iFlag = 0, $iFormat = 1, $fRecursion = True, $sDelim = @CRLF, $fOpenDLL = True)
    Local $hSearch, $sFile, $sReturn = '', $aD
    Local Static $hDll
    If StringRight($sPath, 1) <> '\' Then $sPath &= '\'
    $hSearch = FileFindFirstFile($sPath & '*')
    If Not @error And $hSearch <> -1 Then
    If $fOpenDLL Then $hDll = DllOpen('kernel32.dll')
    While True
    $sFile = FileFindNextFile($hSearch)
    If @error Then ExitLoop
    If @extended Then
    $aD = DllCall($hDll, 'dword', 'GetFileAttributesW', 'wstr', $sPath & $sFile)
    If @error Or BitAND($aD[0], 0x400) Then ContinueLoop
    If StringRegExp($sPath & $sFile, $sPattern) And ($iFlag = 0 Or $iFlag = 2) Then $sReturn &= $sPath & $sFile & '\' & $sDelim
    If $fRecursion Then $sReturn &= _RecursiveFileListToArray($sPath & $sFile & '\', $sPattern, $iFlag, 0, True, $sDelim, False)
    ContinueLoop
    EndIf
    If StringRegExp($sFile, $sPattern) And ($iFlag = 0 Or $iFlag = 1) Then $sReturn &= $sPath & $sFile & $sDelim
    WEnd
    FileClose($hSearch)
    If $fOpenDLL Then DllClose($hDll)
    EndIf
    If $iFormat = 2 Then $iFormat = 3
    If $iFormat And $sReturn = '' Then Return StringSplit($sReturn, '', $iFormat)
    If $iFormat Then Return StringSplit(StringTrimRight($sReturn, StringLen($sDelim)), $sDelim, $iFormat)
    Return $sReturn
    EndFunc ;==>_RecursiveFileListToArray

    [/autoit]
  • Hallo Oskar,

    vorerst wirklich vielen Dank für deine Bemühungen. Dein Skript funktioniert tadellos und macht genau das, was ich wollte und nicht zustande gebracht habe.


    Wie kann ich mich dafür bedanken?

    LG Stefan

    PS: Habe das Skript noch mit einer rekursiven Löschfunktion für leere Verzeichnisse im Quellverzeichnis ergänzt.

    Mit den DllCalls habe ich mich bisher noch nicht beschäftigt - ist für einen Anfänger auch ziemlich "heavy" - ABER: man kann von deinem Code wirklich nur lernen.
    Wird aber noch einige Zeit dauern, bis ich alles kapiert habe.

    2 Mal editiert, zuletzt von mr_merlin (6. November 2013 um 10:56)