Bilder auf Netzlaufwerk aus mehreren Ordner zusammenziehen

  • Hallo zusammen

    Ich habe vor kurzem mit AutoIt angefangen und bin begeistert. normalerweise kann ich die meisten kleineren Problem mit der Hilfe und dem Forum lösen.
    Nun stehe ich vor folgendem Problem:
    Ich habe eine Videokamera installiert welche jede Sekunde ein Bild macht und dieses auf einem netzlaufwerk ablegt.
    Das Problem ist nun das jedes Bild in einen eigenen Ordner gespeichert wird. Des weiteren ist es So das die Kamera immer ornder erstellt von 000 bis 999, welche wieder Unterordner enthalten von 000 bis 999 in welchem die Bilder (die bilder haben immer den gleichen Namen E00000.jpg) sind(Siehe Anhang).
    Ich möchte nun ein Skript erstellen welches alles alle Bilder in einen Ordner kopiert und sie fortlaufend benennt: von 00001 bis .....
    Ist sowas möglich? ich habe mir überlegt das Problem mit FileMove zu lösen, aber habe keine ahnung wie ich das mit den Verzeichnissen hinbekomme.

    Hoffe ich habe mich einigermassen verständlich ausgedrückt und bei Fragen fragt.

    Storyteller

    Dateien

    Make it idiot proof, and someone will build a better idiot!

    Ich würd so gern die Welt verändern, aber Gott gibt mir den Quellcode nicht.

    Einmal editiert, zuletzt von Storyteller (16. März 2010 um 14:33)

  • Hi,

    Spoiler anzeigen
    [autoit]


    ;Trag hier den Start Ordner auf dem Netzwerk ein
    Global $checkdir = "c:\autoit"
    ;Trag hier den Ordner ein, in den die Dateien verschoben werden sollen
    Global $movedir = "c:\move\"
    ;array für JPG Dateien
    Global $arfiles
    ;Lies alle jpg mit vollem Pfad in array
    $arfiles = _GetFilesFolder_Rekursiv ($checkdir, "jpg", 0)
    If @error Then
    MsgBox (0,"Files", "No files found", 5)
    Else
    ;Schleife übe Array
    For $i = 1 To UBound ($arfiles) - 1
    ;zum testen FileCopy
    If StringInStr ($arfiles [$i], "info.jpg") Then ContinueLoop
    FileCopy ($arfiles [$i], $movedir & $i & ".jpg")
    ;wenn erfolgreich getestet entferne FileCopy und schalte FileMove scharf
    ;FileMove ($arfiles [$i], $movedir & $i & ".jpg")
    Next
    EndIf

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

    ;==================================================================================================
    ; Function Name: _GetFilesFolder_Rekursiv($sPath [, $sExt='*' [, $iDir=-1 [, $iRetType=0 ,[$sDelim='0']]]])
    ; Description: recursive listing of files and/or folders
    ; Parameter(s): $sPath Basicpath of listing ('.' -current path, '..' -parent path)
    ; $sExt Extension for file selection '*' or -1 for all (Default)
    ; $iDir -1 Files+Folder(Default), 0 only Files, 1 only Folder
    ; optional: $iRetType 0 for Array, 1 for String as Return
    ; optional: $sDelim Delimiter for string return
    ; 0 -@CRLF (Default) 1 -@CR 2 -@LF 3 -';' 4 -'|'
    ; Return Value(s): Array (Default) or string with found pathes of files and/or folder
    ; Array[0] includes count of found files/folder
    ; 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

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

    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

    [/autoit]

    ;-))
    Stefan

  • Danke dir das Skript ist super, und funktioniert.
    Das Problem ist das es extrem viele Bilder sind ( die Kamera macht jede Sekunde 1 Bild), d.h das Array wird ziemlich gross, was mein Computer glaube ich nicht speichern kann, bzw Verarbeiten kann. Gibt es nicht ne möglichkeit die Bilder direkt zu kopieren?

    Make it idiot proof, and someone will build a better idiot!

    Ich würd so gern die Welt verändern, aber Gott gibt mir den Quellcode nicht.

  • Ok ist irgenwie einleuchtend.

    kann man das Skript so umschreiben, das alles in eine txt Datei geschrieben wird. und dann ausgelesen wird?
    Sollte doch eigentlich möglich sein oder nicht? Da ich genug Speicherplatz habe, wäre das glaube ich besser.

    Storyteller

    Make it idiot proof, and someone will build a better idiot!

    Ich würd so gern die Welt verändern, aber Gott gibt mir den Quellcode nicht.

  • Hi,

    anderer Ansatz:

    [autoit]


    #include <file.au3>
    $movedir = "c:\move\"

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

    RunWait (@ComSpec & " /c dir d:\kamera\*.jpg /s /b >" & @ScriptDir & "\kamera_jpg.txt")
    $file = FileOpen (@ScriptDir & "\kamera_jpg.txt", 0)
    For $i = 1 To _FileCountLines (@ScriptDir & "\kamera_jpg.txt")
    $line = FileReadLine ($file, $i)
    FileCopy ($line, $movedir & $i & ".jpg")
    Next
    FileClose ($file)

    [/autoit]

    ;-))
    Stefan

  • Ok danke für dein Vorschlag, da ich aber noch Anfänger bin, könntest dur mir kurz erklären was das Skript macht?
    Verstehe es nicht so ganz.

    Danke
    Storyteller

    Make it idiot proof, and someone will build a better idiot!

    Ich würd so gern die Welt verändern, aber Gott gibt mir den Quellcode nicht.

  • Hi,

    zur Not gibt es immer noch das Helpfile!

    [autoit]


    Global $movedir = "c:\move\"

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

    ;Starte dir Dos Befehl mit Parameter /s (Unterverzeichnisse) /b (einfaches Format) und speichere in Datei kamera_jpg.txt im Scriptverzeichnis
    ;warte auf Beendigung
    RunWait (@ComSpec & " /c dir d:\kamera\*.jpg /s /b >" & @ScriptDir & "\kamera_jpg.txt")
    ;zeige Textdatei und warte auf ende von notepad
    ShellExecuteWait ("notepad.exe", @ScriptDir & "\kamera_jpg.txt")
    ;Öffne Datei im Read Mode
    $file = FileOpen (@ScriptDir & "\kamera_jpg.txt", 0)
    ;Schleife von 1 bis Zeilenanzahl von Datei
    For $i = 1 To _FileCountLines (@ScriptDir & "\kamera_jpg.txt")
    ;lies Zeile in Variable
    $line = FileReadLine ($file, $i)
    ;Kopiere, wenn Datei nicht info.jpg und benenne um
    If Not StringInStr ($line, "info.jpg") Then FileCopy ($line, $movedir & $i & ".jpg"
    Next
    ;schliesse Datei
    FileClose ($file)

    [/autoit]

    ;-))
    Stefan

  • Das Problem ist das es extrem viele Bilder sind [...], d.h das Array wird ziemlich gross, was mein Computer glaube ich nicht speichern kann, bzw Verarbeiten kann. Gibt es nicht ne möglichkeit die Bilder direkt zu kopieren?


    Ich glaube zwar weniger das das Array dermaßen groß wird aber natürlich gibt es eine spezielle Lösung für diesen Fall.
    Wenn es tatsächlich nur eine Verzeichnisebene gibt dann lässt sich das z.B. der Einfachheit halber folgendermaßen lösen:

    Spoiler anzeigen
    [autoit]

    MoveFilePics("E:\Temp\Test", "C:\Windows")

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

    Func MoveFilePics($sStartdir, $sTargDir)
    Local $iFFFFDirs, $iFFFFFiles, $sFFNFDirs, $sFFNFFiles, $iCounter = 1

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

    If StringRight($sStartdir, 1) = '\' Then $sStartdir = StringTrimRight($sStartdir, 1)
    If Not FileExists($sStartdir) Then Return SetError(1, 0, 0)

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

    $iFFFFDirs = FileFindFirstFile($sStartdir & '\*')
    If $iFFFFDirs = -1 Then Return SetError(2, 0, 0)

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

    While True
    $sFFNFDirs = FileFindNextFile($iFFFFDirs)
    If @error Then ExitLoop
    If @extended Then
    $iFFFFFiles = FileFindFirstFile($sStartdir & '\' & $sFFNFDirs & '\E00000.jpg')
    If $iFFFFFiles <> -1 Then
    While True
    $sFFNFFiles = FileFindNextFile($iFFFFFiles)
    If @error Then ExitLoop

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

    ConsoleWrite('FileMove("' & $sStartdir & '\' & $sFFNFDirs & '\E00000.jpg, "' & $sTargDir & '\' & StringFormat('%06d.jpg")', $iCounter) & @CRLF)
    $iCounter += 1
    WEnd
    EndIf
    EndIf

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

    WEnd

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

    EndFunc ;==>MoveFilePics

    [/autoit]

    Wenn es doch mehr Verzeichnisebenen sind wäre eine Möglichkeit das rekursiv zu lösen:

    Spoiler anzeigen
    [autoit]

    MoveFilePicsRek("E:\Temp\Test", "C:\Windows")

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

    Func MoveFilePicsRek($sStDir, $sTargDir, $sPat = 'E00000.jpg', $iCounter = 1)
    Local $FFFF, $FFNF

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

    If StringRight($sStDir, 1) = '\' Then $sStDir = StringTrimRight($sStDir, 1)
    If Not FileExists($sStDir) Then Return SetError(2, 0, 0)

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

    $FFFF = FileFindFirstFile($sStDir & '\*')
    If $FFFF <> -1 Then
    Do
    $FFNF = FileFindNextFile($FFFF)
    If @error Then ExitLoop
    If @extended Then
    $iCounter = MoveFilePicsRek($sStDir & '\' & $FFNF, $sTargDir, $sPat, $iCounter)
    Else
    If $FFNF = $sPat Then
    ConsoleWrite('FileMove("' & $sStDir & '\' & $sPat & '", "' & $sTargDir & '\' & StringFormat('%06d.jpg")', $iCounter) & @CRLF)
    $iCounter += 1
    EndIf
    EndIf
    Until 0
    EndIf
    Return $iCounter
    EndFunc ;==>MoveFilePicsRek

    [/autoit]

    und eine weitere es iterativ zu lösen (Wäre die bessere Lösung je mehr Verzeichnisebenen es gibt - ansonsten halt rekursiv):

    Spoiler anzeigen
    [autoit]

    MoveFilePicsIt("E:\Temp\Test", "C:\Windows")

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

    Func MoveFilePicsIt($sStDir, $sTargDir, $sPat = 'E00000.jpg')
    Local $cSQueue = ObjCreate("System.Collections.Queue")
    If @error Then Return SetError(1, 1, -1)
    Local $FFFF, $FFNF, $sDir, $iCounter = 1

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

    If StringRight($sStDir, 1) = '\' Then $sStDir = StringTrimRight($sStDir, 1)
    If Not FileExists($sStDir) Then Return SetError(2, 0, "")

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

    $cSQueue.Enqueue($sStDir)

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

    While $cSQueue.Count > 0
    $sDir = $cSQueue.Dequeue
    $FFFF = FileFindFirstFile($sDir & '\*')
    If $FFFF <> -1 Then
    Do
    $FFNF = FileFindNextFile($FFFF)
    If @error Then ExitLoop
    If @extended Then
    $cSQueue.Enqueue($sDir & '\' & $FFNF)
    Else
    If $FFNF = $sPat Then
    ConsoleWrite('FileMove("' & $sDir & '\' & $sPat & '", "' & $sTargDir & '\' & StringFormat('%06d.jpg")', $iCounter) & @CRLF)
    $iCounter += 1
    EndIf
    EndIf
    Until 0
    EndIf
    WEnd
    EndFunc ;==>MoveFilePicsIt

    [/autoit]


    Ich hab dir statt einem FileMove mal nur ein Consolewrite eingebaut so dass du dir dein FileMove entsprechend selbst einbauen kannst.

  • Danke dir vielmals ojo!
    Das Skript ist genau das richtige!
    Habs noch ein bisschen angepasst, damit es automatisch das netzlaufwerk verbindet usw.
    Aber die Hauptarbeit ist von dir.

    danke dir vielmals. :)

    Storyteller

    Make it idiot proof, and someone will build a better idiot!

    Ich würd so gern die Welt verändern, aber Gott gibt mir den Quellcode nicht.

  • Ich glaube zwar weniger das das Array dermaßen groß wird

    Ich sollte es mal testen wie gross es wird sind etwa 500'000 Bilder und jede Sekunde werden es mehr.... Ich glaube das gibt doch noch ein stattliches Array ;) .
    Ich habe mal die Lösung von ojo weiterentwickelt, werde aber wenn ich Zeit habe mal dein Lösungsansatz anschauen. Will ja was dazulernen und deine lösung scheint mir interesant zu sein.

    So long
    Storyteller

    Make it idiot proof, and someone will build a better idiot!

    Ich würd so gern die Welt verändern, aber Gott gibt mir den Quellcode nicht.