Ordner in Laufwerk suchen...

  • Hallihallo,

    ich möchte gern einen bestimmten Ordner auf dem Laufwerk finden, auf dem auch das Skript ist...

    Wie stelle ich das an ?
    Bei FileFindFirstFile brauche ich ja den genauen Pfad zur Datei.
    Ich möchte aber einen Ordner 'Wanted' suchen.

    Jemand 'ne Idee ?


    Gruß
    Greenhorn


    • Offizieller Beitrag

    Also was jetzt?
    - du kennst den Ordnernamen
    - du weißt aber nicht auf welchem Laufwerk
    - du weißt nicht in welchem anderen Verzeichnis er sein könnte

    ==> also rekursiv ein Laufwerk nach dem anderen durchsuchen

    So gehts, nur noch in einer Schleife laufen lassen um alle Laufwerke zu durchsuchen.

    Spoiler anzeigen
    [autoit]

    #include <array.au3>

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

    $StartPfad = "C:\"
    $SuchOrdner = "ORDNER-NAME"

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

    $Daten = _GetFileList($StartPfad, "n",1) ; erzeugt Array mit allen Ordnernamen
    $ret = _ArraySearch($Daten, $SuchOrdner,1,0,0,True) ; durchsucht nach Ordner
    If $ret > 0 Then MsgBox(0, '', $Daten[$ret]) ; gibt den kpl.Pfad zurück

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

    ; AutoIt Version: 3.0
    ; Language: English
    ; Platform: Win9x/NT/XP
    ; Author: jos van der Zande
    ;
    ; Find files in directory and subdirectories and return it in an Array, all coded in Autoit3
    ;
    ;********************************************************************************
    ;Recursive search for filemask
    ;********************************************************************************

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

    Func _GetFileList($T_DIR,$T_MASK,$DIR_ONLY=0)
    Dim $N_DIRNAMES[200000] ; max number of directories that can be scanned
    Local $N_DIRCOUNT = 0
    Local $N_FILE
    Local $N_SEARCH
    Local $N_TFILE
    Local $N_OFILE
    Local $T_FILENAMES
    Local $T_FILECOUNT
    Local $T_DIRCOUNT = 1
    Local $FILEMASK
    ; check Filemask \ for empty File-Array by GetDirOnly
    If $FILEMASK = "n" Then $FILEMASK = "*.no"
    ; remove the end \ If specified
    If StringRight($T_DIR,1) = "\" Then $T_DIR = StringTrimRight($T_DIR,1)
    $N_DIRNAMES[$T_DIRCOUNT] = $T_DIR
    ; Exit if base dir doesn't exists
    If Not FileExists($T_DIR) Then Return 0
    ; keep on looping until all directories are scanned
    While $T_DIRCOUNT > $N_DIRCOUNT
    $N_DIRCOUNT = $N_DIRCOUNT + 1
    ; find all subdirs in this directory and save them in a array
    $N_SEARCH = FileFindFirstFile($N_DIRNAMES[$N_DIRCOUNT] & "\*.*")
    While 1
    $N_FILE = FileFindNextFile($N_SEARCH)
    If @error Then ExitLoop
    ; skip these references
    If $N_FILE = "." Or $N_FILE = ".." Then ContinueLoop
    $N_TFILE = $N_DIRNAMES[$N_DIRCOUNT] & "\" & $N_FILE
    ; if Directory than add to the list of directories to be processed
    If StringInStr(FileGetAttrib( $N_TFILE ),"D") > 0 Or _
    StringInStr(FileGetAttrib( $N_TFILE ),"D,H,S") > 0 Then
    $T_DIRCOUNT = $T_DIRCOUNT + 1
    $N_DIRNAMES[$T_DIRCOUNT] = $N_TFILE
    EndIf
    Wend
    FileClose($N_SEARCH) ; find all Files that mtach the MASK
    $N_SEARCH = FileFindFirstFile($N_DIRNAMES[$N_DIRCOUNT] & "\" & $T_MASK )
    If $N_SEARCH = -1 Then ContinueLoop
    While 1
    $N_FILE = FileFindNextFile($N_SEARCH)
    If @error Then ExitLoop
    ; skip these references
    If $N_FILE = "." Or $N_FILE = ".." Then ContinueLoop
    $N_TFILE = $N_DIRNAMES[$N_DIRCOUNT] & "\" & $N_FILE
    ; if Directory than add to the list of directories to be processed
    If StringInStr(FileGetAttrib( $N_TFILE ),"D") = 0 Or _
    StringInStr(FileGetAttrib( $N_TFILE ),"D,H,S") = 0 Then
    $T_FILENAMES = $T_FILENAMES & $N_TFILE & @CR
    $T_FILECOUNT = $T_FILECOUNT + 1
    ;MsgBox(0,'filecount ' & $T_FILECOUNT ,$N_TFILE)
    EndIf
    Wend
    FileClose($N_SEARCH)
    Wend
    If $DIR_ONLY = 0 Then
    $T_FILENAMES = StringTrimRight($T_FILENAMES,1)
    $N_OFILE = StringSplit($T_FILENAMES,@CR)
    Return( $N_OFILE )
    Else
    ReDim $N_DIRNAMES[$N_DIRCOUNT+1]
    $N_DIRNAMES[0] = $N_DIRCOUNT
    Return $N_DIRNAMES
    EndIf
    EndFunc ;==>_GetFileList

    [/autoit]
  • Er weiß schon auf welchem Laufwerk - nämlich dem auf dem das Skript liegt.

    Hier mal eine etwas speziellere Methode.
    Dürfte deutlich schneller sein als erst alles einzulesen und dann zu durchsuchen.
    Allerdings wird hierbei die Suche nach dem ersten erfolgreichen Fund gleich abgebrochen - soll heißen:
    Gibt es mehrere Ordner mit diesem Namen wird trotzdem nur eine gefunden.
    Wenn das dennoch reichen sollte:

    [autoit]

    $Verzeichnisname = 'Wanted'

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

    $Time = TimerInit()
    $Ordner = _DirSearch(StringLeft(@ScriptDir, 2), $Verzeichnisname)

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

    MsgBox(0, "Ordner", $Ordner & @CRLF & "Suchzeit: " & Round(TimerDiff($Time) / 1000, 2) & "s")

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

    ; ======================================================================================
    ;Function Name: DirSearch()
    ;Description: Sucht eine Verzeichnis rekursiv in einem angegebenen Verzeichnis
    ;Parameter(s): $recdir: Das Startverzeichnis in dem gesucht werden soll
    ; $Dsrch: Verzeichnisname nach dem gesucht werden soll
    ;Return Value(s): Erfolg - Gibt den Pfad des Ordners zurück
    ; Misserfolg - Gibt einen Nullstring zurück und setzt @error auf 1
    ;Author(s): AspirinJunkie (https://autoit.de/www.German-nLite.de)
    ;=======================================================================================

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

    Func _DirSearch($recdir, $Dsrch)

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

    Local $recdirobj, $recdirpth, $recdirsmlng, $recdirec, $Path

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

    If StringRight($recdir, 1) = '\' Then $recdir = StringTrimRight($recdir, 1)

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

    $recdirobj = ObjCreate('Scripting.FileSystemObject')
    If Not @error Then

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

    $recdirpth = $recdirobj.GetFolder ($recdir & '\')
    $recdirsmlng = $recdirpth.SubFolders
    For $recdirec In $recdirsmlng

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

    If $recdirec.Name = $Dsrch Then
    Return $recdir & '\' & $recdirec.Name
    EndIf

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

    $Path = _DirSearch($recdir & '\' & $recdirec.Name, $Dsrch)
    If Not @error Then Return $Path
    Next
    EndIf

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

    SetError(1)
    Return ''

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

    EndFunc ;==>_DirSearch

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

    ;=======================================================================================

    [/autoit]

    2 Mal editiert, zuletzt von AspirinJunkie (8. Juli 2007 um 12:33)

  • Sorry - versteh noch nicht wirklich was du meinst.
    Meinst du mit "Dir-Befehlen" Kommandozeilenbefehle?
    Kannst du das bitte nochmal genauer erläutern?

    Wenn es mehrere Ordner mit diesem Namen gibt kann man die Funktion auch einfach entsprechend umschreiben so das man einfach ein Array mit allen gesuchten Pfaden zurück bekommt:

    [autoit]

    $Verzeichnisname = 'Wanted'
    $Ordner = _DirSearch(StringLeft(@ScriptDir, 2), $Verzeichnisname)

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

    If not @error Then
    _ArrayDisplay($Ordner, "Test")
    EndIf

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

    ; ======================================================================================
    ;Function Name: DirSearch()
    ;Description: Sucht ein Verzeichnis rekursiv in einem angegebenen Verzeichnis
    ;Parameter(s): $recdir: Das Startverzeichnis in dem gesucht werden soll
    ; $Dsrch: Verzeichnisname nach dem gesucht werden soll
    ;Return Value(s): Erfolg - Gibt ein Array mit den Pfaden zu den gefundenen Ordnern zurück
    ; Misserfolg - RückgabeArray[0] = 0 und @error = 1
    ;Author(s): AspirinJunkie (https://autoit.de/www.German-nLite.de)
    ;=======================================================================================

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

    Func _DirSearch($recdir, $Dsrch, $Instanz = 1)

    Local $recdirobj, $recdirpth, $recdirsmlng, $recdirec, $Path

    If StringRight($recdir, 1) = '\' Then $recdir = StringTrimRight($recdir, 1)

    If $Instanz Then
    Global $DSearchAusgabe[1]
    EndIf

    $recdirobj = ObjCreate('Scripting.FileSystemObject')
    If Not @error Then

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

    $recdirpth = $recdirobj.GetFolder ($recdir & '\')
    $recdirsmlng = $recdirpth.SubFolders
    For $recdirec In $recdirsmlng

    If $recdirec.Name = $Dsrch Then
    ReDim $DSearchAusgabe[UBound($DSearchAusgabe) + 1]
    $DSearchAusgabe[0] += 1
    $DSearchAusgabe[UBound($DSearchAusgabe) - 1] = $recdir & '\' & $recdirec.Name
    EndIf

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

    _DirSearch($recdir & '\' & $recdirec.Name, $Dsrch, 0)
    Next
    EndIf

    If $DSearchAusgabe[0] = 0 Then SetError(1)
    Return $DSearchAusgabe

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

    EndFunc ;==>_DirSearch

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

    ;=======================================================================================

    [/autoit]
  • Na dann testen wir es doch mal ;)

    Da mir nicht bekannt ist das man mit dem Dir-Befehl suchen kann vermute ich das du meinst das du mit dem Befehl die Unterordner in einem Ordner einlesen willst und dann checken ob der gesuchte Ordner dabei ist - versteh ich das so richtig?

    Hab also mal zu Testzwecken 2 Funktionen gebastelt welche beide die Unterordner in einem Ordner auf Übereinstimmung mit einer Sucheingabe untersuchen.
    Ist der gesuchte Ordner dabei wird sein Pfad ausgegeben.

    Das Ergebnis ist bei beiden Funktionen das selbe - nur der Weg dorthin ist unterschiedlich - die eine nutzt COM-Objekte - die andere liest die Ordner über den Dir-Befehl aus.

    Hier nun das Vergleichsskript:

    [autoit]

    #include <Constants.au3>

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

    $Time = TimerInit()
    For $i = 1 To 200
    $OutputKommando = _ListDirKommandozeile("C:\Windows", "system32")
    Next
    $DirTime = TimerDiff($Time) / 200


    $Time = TimerInit()
    For $i = 1 To 200
    $OutputCOM = _ListDirCOM("C:\Windows", "system32")
    Next
    $COMTime = TimerDiff($Time) / 200


    MsgBox(0,"Speed-Vergleich", "Kommandozeilenversion:" & @CRLF & " Ergebnis: " & $OutputKommando & @CRLF & ' Zeit: ' & Round($DirTime,2) & ' ms' & @CRLF & @CRLF & "COM-Objekt-Version:" & @CRLF & " Ergebnis: " & $OutputCOM & @CRLF & ' Zeit: ' & Round($COMTime,2) & ' ms' & @CRLF & @CRLF & "Verhältnis: " & Round($DirTime / $COMTime) & ':1')


    ;Liest die Ordner über ein COM-Objekt ein
    Func _ListDirCOM($Pfad, $Suche)

    Local $recdirobj, $recdirpth, $recdirsmlng, $recdirec, $Path
    Local $Output[1]

    If StringRight($Pfad, 1) = '\' Then $Pfad = StringTrimRight($Pfad, 1)

    $recdirobj = ObjCreate('Scripting.FileSystemObject')

    If Not @error Then

    $recdirpth = $recdirobj.GetFolder ($Pfad & '\')
    $recdirsmlng = $recdirpth.SubFolders

    For $recdirec In $recdirsmlng

    If $recdirec.Name = $Suche Then
    return $Pfad & '\' & $recdirec.Name
    EndIf

    Next
    EndIf

    SetError(1)

    Return 0

    EndFunc

    ;Liest die Ordner über die Kommandozeile ein
    Func _ListDirKommandozeile($Pfad, $Suche)
    Local $Text = ''

    $PID = Run(@ComSpec & " /c dir " & $Pfad & ' /AD', @ScriptDir, @SW_HIDE, $STDOUT_CHILD)

    While 1
    $Text &= StdoutRead($PID)
    If @error Then ExitLoop
    WEnd

    If StringRegExp($Text, "\d{2}\.\d{2}\.\d{4}\s{2}\d{2}:\d{2}\s{4}<DIR>\s{10}" & $Suche, 0) Then
    return $Pfad & '\' & $Suche
    Else
    SetError(1)
    Return 0
    EndIf
    EndFunc

    [/autoit]


    P.S: Wenn ich das mit dem Dir-Befehl falsch verstanden haben sollte bin ich an einer Möglichkeit effektiver mit diesem zu arbeiten durchaus sehr interessiert.


    Edit: Oh - da hab ich beim Kopieren wohl etwas vergessen gehabt.... :rolleyes:

    3 Mal editiert, zuletzt von AspirinJunkie (8. Juli 2007 um 16:18)

    • Offizieller Beitrag

    Hallo,

    man kann mit dem Dir-Befehl auch suchen, wenn man z.B. alle Ordner haben will die mit "system" anfangen und sich auf Laufwerk C: befinden, muss man von c:\ folgendes eingeben:

    Code
    DIR system* /S /A:D /B
  • Als erstes möchte ich mich für das rege Interesse an diesem Thema bedanken,ihr seid die Besten !!! :)
    Hätte nicht gedacht, das das Thema soviel Beachtung findet. 8o

    Sorry, wenn ich mich heute Morgen etwas ungenau ausgedrückt habe, war übermüdet... ;)

    Also, das Skript soll eine EXE in einem Ordner ausführen, als Launcher sozusagen.
    Das ganze befindet sich auf einem USB Stick.
    EXE- und Ordnername sind bekannt.

    Mein Ziel ist es nun zu erreichen, dass der Launcher und der Ordner an verschiedenen Orten liegen können, da ja jeder seine Launcher und Programmordner woanders hat.

    Das ganze könnte ich jetzt natürlich über eine INI steuern, aber mich hat gestern Nacht/heute Morgen beschäftigt, ob es nicht auch so gehen könnte, und wenn ja mit welcher Zeitverzögerung ich durch das Suchen rechnen muss.
    Daher habe ich die Suche auch auf den Ordner beschränkt, um die Suchzeit zu verkürzen...

    Heute Morgen, kurz vor'm Einschlafen, fiel mir dann noch _FileListToArray ein !
    Damit könnte man auch eine Suchmaschine basteln...

    Ich werde nachher die Skripte von euch austesten und mich dann wieder melden. (muss jetzt kurz zur Tanke, Kühlschrank ist leer...)


    Gruß
    Greenhorn
    P.S.: Ist schon komisch, mir ist irgendwie aufgefallen, dass man mit AutoIt alles mögliche an Dateifunktionen hat, bei Ordnern sieht's da schon anders aus...


    Einmal editiert, zuletzt von Greenhorn (8. Juli 2007 um 16:30)

  • Wow das ist ja tatsächlich um einiges schneller als meine bisherige Lösung.
    Bei meinen Tests etwa um den Faktor 6!
    Nicht schlecht.

    Demnach wäre die beste Lösung für das hier wohl nun folgende:

    [autoit]

    ; ======================================================================================
    ;Function Name: _FileSearch()
    ;Description: Sucht ein Verzeichnis rekursiv in einem angegebenen Verzeichnis
    ;Parameter(s): $Pfad: Das Startverzeichnis in dem gesucht werden soll
    ; $Suche: Verzeichnisname nach dem gesucht werden soll
    ;Return Value(s): Erfolg - Gibt ein Array mit den Pfaden zu den gefundenen Ordnern zurück
    ; Misserfolg - RückgabeArray[0] = 0 und @error = 1
    ;=======================================================================================

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

    Func _DirSearch($Pfad, $Suche)
    Local $Text


    $PID = Run(@ComSpec & " /c DIR " & $Suche & " /S /A:D /B", $Pfad, @SW_HIDE, $STDOUT_CHILD)

    While 1
    $Text &= StdoutRead($PID)
    If @error Then ExitLoop
    WEnd

    $Text = StringSplit(StringStripCR(StringTrimRight($Text, 1)), @LF)

    If $Text[0] = 1 And $Text[1] = '' Then SetError(1)
    Return $Text

    EndFunc ;==>_DirSearch

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

    ;=======================================================================================

    [/autoit]


    Danke Jungs - wiedermal ne ganze Menge gelernt hier bei euch :)


    Edit: Ich sehe gerade das die Sache doch noch einen Haken bei mir hat:
    Wenn der Ordner Unterverzeichnisse enthält werden alle Unterverzeichnisse als Ergebnis ausgegeben anstatt nur den Pfad zum eigentlichen Stammverzeichnis.
    Kann man das auch über entsprechende Kommandozeilenparameter lösen?

    Einmal editiert, zuletzt von AspirinJunkie (8. Juli 2007 um 17:26)

  • AspirinJunkie

    Dein letztes Skript musste ich ein wenig umschreiben, damit es funktioniert.
    Du hast aus versehen die Variable $Search in den Run Befehl unter WorkingDirectory gesetzt... ;)

    So funzt es hervorragend :

    Spoiler anzeigen
    [autoit]

    Func _DirSearch($Pfad, $Suche)
    Local $Text, $Found


    $PID = Run(@ComSpec & " /c DIR " & $Pfad & " /S /A:D /B", '', @SW_HIDE, $STDOUT_CHILD)

    While 1
    $Text = StdoutRead($PID)
    If @error Then ExitLoop
    If StringInStr($Text, $Suche) Then $Found &= $Text
    WEnd

    $Found = StringSplit(StringStripCR(StringTrimRight($Found, 1)), @LF)

    If $Found[0] = 1 And $Found[1] = '' Then SetError(1)
    Return $Found

    EndFunc ;==>_DirSearch

    [/autoit]

    Vielen Dank aneuch alle ! =)


    Gruß
    Greenhorn


    • Offizieller Beitrag
    Zitat

    Original von AspirinJunkie

    Danke Jungs - wiedermal ne ganze Menge gelernt hier bei euch :)


    Edit: Ich sehe gerade das die Sache doch noch einen Haken bei mir hat:
    Wenn der Ordner Unterverzeichnisse enthält werden alle Unterverzeichnisse als Ergebnis ausgegeben anstatt nur den Pfad zum eigentlichen Stammverzeichnis.
    Kann man das auch über entsprechende Kommandozeilenparameter lösen?

    Ich habe deine Code mal etwas erweitert, jetzt sollte es funktionieren:

    Spoiler anzeigen
    [autoit]

    #include <Constants.au3>
    #include <Array.au3>

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

    $Verzeichnisname = "Startmenü"
    $Ordner = _DirSearch($Verzeichnisname, "C:\Dokumente und Einstellungen")
    _ArrayDisplay($Ordner, "Ausgabe")

    ; ======================================================================================
    ; Function Name: DirSearch()
    ; Description: Sucht ein Verzeichnis rekursiv in einem angegebenen Verzeichnis
    ; Parameter(s): $szSuche: Verzeichnisname nach dem gesucht werden soll
    ; $szStartPfad: Das Startverzeichnis in dem gesucht werden soll
    ; Return Value(s): Erfolg - Gibt ein Array mit den Pfaden zu den gefundenen Ordnern zurück
    ; Misserfolg - RückgabeArray[0] = 0 und @error = 1
    ;=======================================================================================
    Func _DirSearch($szSuche, $szStartPfad = @ScriptDir)
    Local $Text = ''
    Local $Output[1]

    If StringRight($szStartPfad,1) <> "\" Then $szStartPfad &= "\"
    $szWD = StringLeft($szStartPfad,3)
    $PID = Run(@ComSpec & " /c DIR " & $szSuche & " /S /A:D /B", $szWD, @SW_SHOW, $STDOUT_CHILD)

    While 1
    $Text &= StdoutRead($PID)
    If @error Then ExitLoop
    WEnd
    $Text = StringSplit(OemToChar($Text), @CRLF)

    ; $szStartPfad für StringRegExp anpassen
    $szStartPfad = StringReplace($szStartPfad, "\", "\\")
    $szStartPfad = StringReplace($szStartPfad, ".", "\.")
    $szStartPfad = StringReplace($szStartPfad, "+", "\+")
    $szStartPfad = StringReplace($szStartPfad, "-", "\-")
    $szStartPfad = StringReplace($szStartPfad, "(", "\(")
    $szStartPfad = StringReplace($szStartPfad, ")", "\)")
    $szStartPfad = StringReplace($szStartPfad, "[", "\[")
    $szStartPfad = StringReplace($szStartPfad, "]", "\]")
    $szStartPfad = StringReplace($szStartPfad, "?", ".")
    $szStartPfad = StringReplace($szStartPfad, "*", ".*")

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

    ; $szSuche für StringRegExp anpassen
    $szSuche = StringReplace($szSuche, "\", "\\")
    $szSuche = StringReplace($szSuche, ".", "\.")
    $szSuche = StringReplace($szSuche, "+", "\+")
    $szSuche = StringReplace($szSuche, "-", "\-")
    $szSuche = StringReplace($szSuche, "(", "\(")
    $szSuche = StringReplace($szSuche, ")", "\)")
    $szSuche = StringReplace($szSuche, "[", "\[")
    $szSuche = StringReplace($szSuche, "]", "\]")
    $szSuche = StringReplace($szSuche, "?", ".")
    $szSuche = StringReplace($szSuche, "*", ".*")

    For $i = 1 To $Text[0]
    If StringRegExp($Text[$i],"(?i)^(" & $szStartPfad & ".*\\" & $szSuche & ")$") Then
    ReDim $Output[UBound($Output) + 1]
    $Output[0] += 1
    $Output[UBound($Output) - 1] = $Text[$i]
    EndIf
    Next

    If $Output[0] = 0 Then SetError(1)
    Return $Output

    EndFunc ;==>_DirSearch

    ;=======================================================================================

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

    ;===============================================================================
    ; Name: OemToChar
    ; Description: Wandelt einen ASCII- in einen ANSI-String
    ; Parameter(s): $szSrc = String der umgewandelt werden soll
    ; Requirement(s): keine
    ; Return Value(s): bei Erfolg: umgewandelter String
    ; bei Fehler: "" und @error = 1
    ; Author(s): bernd670
    ;
    ;===============================================================================
    Func OemToChar ($szSrc)
    ;~ Private Declare Function OemToChar Lib "user32.dll" Alias "OemToCharA" (ByVal lpszSrc As String, ByVal lpszDst As String) As Long

    Local $strSrc = DllStructCreate("char[" & StringLen($szSrc) + 1 & "]")
    Local $strDst = DllStructCreate("char[" & StringLen($szSrc) * 2 + 1 & "]")
    DllStructSetData($strSrc,1,$szSrc)
    DllStructSetData($strDst,1,0)

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

    Local $lRetVal = DllCall("user32.dll", "long", "OemToChar", "ptr", DllStructGetPtr($strSrc), "ptr", DllStructGetPtr($strDst))
    If IsArray($lRetVal) And $lRetVal[0] = 1 Then
    Return SetError(0,0,DllStructGetData($strDst,1))
    EndIf

    Return SetError(1,0,"")
    EndFunc

    [/autoit]


    @1: Noch einen kleinen Bug gefixt!
    @2: Umlaute wurden nicht korrekt zurückgegeben -> gefixt!

  • Mir ist aufgefallen, dass bei der DIR-Methode der Pfad keine Leerzeichen entalten darf ! 8o

    Wenn man Leerzeichen im Pfad hat werden Ordner angezeigt, die den einen oder anderen Namen enthalten ! (...und manchmal auch andere Ordner)


    Gruß


    • Offizieller Beitrag

    Mit Leerzeichen habe ich keine Probleme!

  • Zitat

    Original von GreenhornDu hast aus versehen die Variable $Search in den Run Befehl unter WorkingDirectory gesetzt... ;)


    Das war nicht aus Versehen sondern Absicht.
    So kann man festlegen in welchem Ordner gesucht werden soll.

    Bernd
    Thx - das mit den Umlauten ist mir noch nicht aufgefallen - hatte bisher scheinbar nur mit Ordnern ohne diese probiert.

    Dennoch funktioniert das noch nicht ganz wie es soll.

    Folgender Aufruf Beispielsweise:

    [autoit]

    $Output = _DirSearch("Windows", "C:\")
    _ArrayDisplay($OutPut, "Test")

    [/autoit]

    Dieser Sollte zumindestens das Windows-Stammverzeichnis als Ergebnis bringen.
    Das einzige Ergebnis ist aber folgendes:

    C:\Windows\system32\config\systemprofile\Lokale Einstellungen\Anwendungsdaten\Microsoft\Windows

    Er findet zwar den Unterordner "Windows" - ignoriert aber das Stammverzeichnis "Windows".

    Dieser Spezialfall (wenn ein Unterordner und ein entsprechendes Stammverzeichnis den selben Namen haben) müsste also noch mit berücksichtigt werden.
    Ich kann mir momentan aber noch nicht ganz vorstellen wie man das am besten umsetzen könnte.

    Trotzdem danke erstmal für die Mithilfe - wär wirklich geil wenn man daraus eine solch performante Suchfunktion basteln könnte...

    • Offizieller Beitrag

    Hi,

    jetzt sollte es funktionieren:

    Spoiler anzeigen
    [autoit]

    #include <Constants.au3>
    #include <Array.au3>

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

    $Verzeichnisname = "Temp"
    $Ordner = _DirSearch($Verzeichnisname, "C:\")
    _ArrayDisplay($Ordner, "Ausgabe")

    ; ======================================================================================
    ; Function Name: DirSearch()
    ; Description: Sucht ein Verzeichnis rekursiv in einem angegebenen Verzeichnis
    ; Parameter(s): $szSuche: Verzeichnisname nach dem gesucht werden soll
    ; $szStartPfad: Das Startverzeichnis in dem gesucht werden soll
    ; Return Value(s): Erfolg - Gibt ein Array mit den Pfaden zu den gefundenen Ordnern zurück
    ; Misserfolg - RückgabeArray[0] = 0 und @error = 1
    ;=======================================================================================
    Func _DirSearch($szSuche, $szStartPfad = @ScriptDir)
    Local $Text = ''
    Local $Output[1]

    If StringRight($szStartPfad,1) <> "\" Then $szStartPfad &= "\"
    $szWD = StringLeft($szStartPfad,3)
    $PID = Run(@ComSpec & " /c DIR * /A:D /B /S", $szWD, @SW_SHOW, $STDOUT_CHILD)

    While 1
    $Text &= StdoutRead($PID)
    If @error Then ExitLoop
    WEnd
    $Text = StringSplit(OemToChar($Text), @CRLF)

    ; $szStartPfad für StringRegExp anpassen
    $szStartPfad = StringTrimRight($szStartPfad,1)
    $szStartPfad = StringReplace($szStartPfad, "\", "\\")
    $szStartPfad = StringReplace($szStartPfad, ".", "\.")
    $szStartPfad = StringReplace($szStartPfad, "+", "\+")
    $szStartPfad = StringReplace($szStartPfad, "-", "\-")
    $szStartPfad = StringReplace($szStartPfad, "(", "\(")
    $szStartPfad = StringReplace($szStartPfad, ")", "\)")
    $szStartPfad = StringReplace($szStartPfad, "[", "\[")
    $szStartPfad = StringReplace($szStartPfad, "]", "\]")
    $szStartPfad = StringReplace($szStartPfad, "?", ".")
    $szStartPfad = StringReplace($szStartPfad, "*", ".*")

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

    ; $szSuche für StringRegExp anpassen
    $szSuche = "\" & $szSuche
    $szSuche = StringReplace($szSuche, "\", "\\")
    $szSuche = StringReplace($szSuche, ".", "\.")
    $szSuche = StringReplace($szSuche, "+", "\+")
    $szSuche = StringReplace($szSuche, "-", "\-")
    $szSuche = StringReplace($szSuche, "(", "\(")
    $szSuche = StringReplace($szSuche, ")", "\)")
    $szSuche = StringReplace($szSuche, "[", "\[")
    $szSuche = StringReplace($szSuche, "]", "\]")
    $szSuche = StringReplace($szSuche, "?", ".")
    $szSuche = StringReplace($szSuche, "*", ".*")
    ConsoleWrite($szStartPfad & @CRLF & $szSuche & @CRLF)

    For $i = 1 To $Text[0]
    If StringRegExp($Text[$i],"(?i)^(" & $szStartPfad & ".*" & $szSuche & ")$") Then
    if UBound($Output) <= ($Output[0] + 1) Then ReDim $Output[UBound($Output) + 100]
    $Output[0] += 1
    $Output[$Output[0]] = $Text[$i]
    EndIf
    Next
    ReDim $Output[$Output[0]+1]
    If $Output[0] = 0 Then SetError(1)
    Return $Output

    EndFunc ;==>_DirSearch

    ;=======================================================================================

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

    ;===============================================================================
    ; Name: OemToChar
    ; Description: Wandelt einen ASCII- in einen ANSI-String
    ; Parameter(s): $szSrc = String der umgewandelt werden soll
    ; Requirement(s): keine
    ; Return Value(s): bei Erfolg: umgewandelter String
    ; bei Fehler: "" und @error = 1
    ; Author(s): bernd670
    ;
    ;===============================================================================
    Func OemToChar ($szSrc)
    ;~ Private Declare Function OemToChar Lib "user32.dll" Alias "OemToCharA" (ByVal lpszSrc As String, ByVal lpszDst As String) As Long

    Local $strSrc = DllStructCreate("char[" & StringLen($szSrc) + 1 & "]")
    Local $strDst = DllStructCreate("char[" & StringLen($szSrc) * 2 + 1 & "]")
    DllStructSetData($strSrc,1,$szSrc)
    DllStructSetData($strDst,1,0)

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

    Local $lRetVal = DllCall("user32.dll", "long", "OemToChar", "ptr", DllStructGetPtr($strSrc), "ptr", DllStructGetPtr($strDst))
    If IsArray($lRetVal) And $lRetVal[0] = 1 Then
    Return SetError(0,0,DllStructGetData($strDst,1))
    EndIf

    Return SetError(1,0,"")
    EndFunc

    [/autoit]
  • Funktioniert 1a, Bernd !!! =)

    Jetzt muss mir jemand nur noch eines Erklären:
    Warum wird bei der Version von AspirinJunkie nur der Inhalt vom letzten Bildschirm der Konsole durchsucht, bzw. angezeigt und bei Bernd's Version nicht ?!? ?(

    Die Grundfunktion ist doch die gleiche, also mit Run -> While -> Return $var...

    Und das mit den Leerzeichen im Pfad..., also wenn ich in der Konsole als Startverzeichnis einen Ordner mit Zahlen angebe (z.B. dir C:\Ordner 5 /a:d /b /s), dann kommt: Datei nicht gefunden.
    Wenn ich als Startverzeicnis z.B. E:\AutoIt Projekte angebe ebenso.

    Spoiler anzeigen


    Gruß
    Greenhorn