Wirklich? Ich kam mir schon so ausgeschlossen vor:
Zitat:
Wir sind hier leider keine Hellseher ...
So, als würde ich gar nicht mehr dazu gehören.
Also, m-werk -
Mein Vorschlag wäre, dass du die eigentliche Suchroutine in eine eigene Prozedur einklammerst. Das ist der beste Weg, da sich diese Prozedur für jedes Unterverzeichnis wieder selbst aufrufen muss. Schließlich willst du ja nicht nur das Hauptverzeichnis C:\ sondern auch C:\Programme usw. durchsuchen?!
Ich schlage vor, dass du dieser Prozedur den Root-Pfad immer mit übergibst und diesen Wert nie änderst. Das passiert natürlich programmtechnisch und würde z.B. (s.
for-Schleife in meinem letzten AUQ-Posting) so aussehen:
Code:
for i := 2 to 25 do
// Laufwerk muss existieren und dem
// gewünschten Typ entsprechen
if(DriveExists(i)) and (IsHD(i)) then
// es muss möglich sein, auf das Laufwerk
// zu wechseln
if(SetCurrentDir(CHR(i + BYTE('A')) + ':\')) then
begin
// rekursive Suchfunktion aufrufen
scanit(CHR(i + BYTE('A')) + ':\');
// die Suche abbrechen, wenn die Datei
// gefunden wurde
if(found) then break;
end;
In der Suchprozedur stellst du dann als erstes fest, wie das aktuelle Verzeichnis heißt, und in der letzten Zeile der Funktion vergleichst du das aktuelle Verzeichnis mit dem übergebenen Root-Pfad. Sind sie unterschiedlich, springst du wieder eine Ebene nach oben.
Wozu?
Das hat mit der Funktion an sich zu tun. Deine Suche startet z.B. in C:\, und die Funktion findet jetzt z.B. das Programme-Verzeichnis. Also wechselt sie in diesen Ordner und ruft sich selbst wieder auf, um die Suche fortzusetzen.
Jetzt mal angenommen, es gäbe keine Unterordner mehr. Wenn die Funktion die gesuchte Datei nicht findet, steckt sie im Programme-Ordner fest, und die Suche würde nicht mehr weitergehen, bzw. keine Ergebnisse mehr liefern. Du musst also wieder eine Ebene nach oben ins Hauptverzeichnis C:\ springen, damit dann z.B. der Windows-Ordner gefunden und durchsucht werden kann. usw. usw.
Code:
procedure scanit(orgPath: string);
var
path : string;
begin
path := GetCurrentDir;
// Suchfunktion
// kommt gleich, und muss HIER REIN!!!
if(Path <> orgPath) then ChDir('..');
end;
Nun zur Suche. Grundlegend kann (!) eine
FindFirst/
FindNext-Suche so aussehen:
Code:
var
res : integer;
ds : TSearchRec;
begin
res := FindFirst('*.*',faAnyFile,ds);
while(res = 0) do
begin
// Anzeige des aktuellen Dateinamens/Verzeichnisses
// im Label der Form
Form1.Label1.Caption := path + '\' + ds.Name;
// ist der Dateiname mit dem Suchnamen identisch?
if(lowercase(ds.Name) = lowercase(szSearchFile)) and
(ds.Attr and faDirectory = 0) then
begin
// Ja!
Found := true;
end
// Nein, es ist aber ein Unterverzeichnis.
// Also, rein da, & weitersuchen!
else if(ds.Attr and faDirectory <> 0) and
(ds.Name <> '.') and (ds.Name <> '..') then
begin
SetCurrentDir(ds.Name);
scanit(orgPath);
end;
// die Suche ist beendet!
if(Found) then break;
res := FindNext(ds);
end;
FindClose(ds);
{mal empfehlenswert ->} Application.ProcessMessages;
end;
Es gibt auch noch andere Varianten mit
repeat-
until, aber ich persönlich benutze seit vergangenen TurboPASCAL-Tagen diese
while-Konstruktion.
Du siehst hier auch gleich meine Bool-Variable. Wenn sie auf TRUE gesetzt wird, wird die Schleife verlassen. Logisch! Die Datei wurde ja gefunden, jede weitere Suche wäre Zeitverschwendung. Du solltest wirklich auch
break verwenden, damit
FindClose in jedem Fall aufgerufen wird.
exit wäre zum Verlassen der Schleife zwar möglich, aber nicht empfehlenswert. Übrigens darf die Bool-Variable keine lokale Variable der Prozedur "scanit" sein!
Übrigens, schöner Nebeneffekt: bei mir benötigte die Funktion beim ersten Durchlauf ca. 10 Sekunden, um auf einem Athlon mit 1GHz die Laufwerke C-H mit insgesamt 26.685 Dateien und 2.206 Ordnern zu durchsuchen. (Ich habe extra mal nach einem Programm auf der H-Partition suchen lassen!)
Das Ganze scheint irgendwie und irgendwo gecacht zu werden, denn jeder weitere Durchlauf benötigte nur noch ca 1.6 Sekunden.
Gruß,
Mathias.