2016-06-26 10 views
0

Ich muss alle Dateien löschen, deren Namen mit "a" beginnen, dann drei beliebige Buchstaben und ".txt" -Erweiterung wie "a123.txt". Hier ist der Code:FindFirst und Fragezeichen

var 
    sFileMask: string; 
    tsrMessage: TSearchRec; 
begin 
    sFileMask := 'c:/a???.txt'; 
    if SysUtils.FindFirst(sFileMask, 0, tsrMessage) = 0 then 
    begin 
    repeat 
     ShowMessage(tsrMessage.Name); 
    until FindNext(tsrMessage) <> 0; 
    SysUtils.FindClose(tsrMessage); 
    end; 
end; 

Ich habe immer gedacht, dass die Fragezeichen bedeuten, ein und nur ein Charakter, aber zu meiner Überraschung festgestellt, dass dieser Code gibt „a.txt“, „a1.txt“ und „a123. txt "Dateinamen. Gibt es eine einfache Möglichkeit, den Code so zu ändern, dass nur Dateien wie "a123.txt" gesucht werden?

Antwort

4

Die einfachste Lösung für Ihren spezifischen Bedarf ist diese zu ersetzen:

ShowMessage(tsrMessage.Name); 

mit diesem

if length(tsrMessage.Name)=8 then ShowMessage(tsrMessage.Name); 

dies stellt sicher, dass die Länge des Dateinamens vier Zeichen genau + die Periode + die Erweiterung. Wie David sagt, gibt es keine Möglichkeit, diese Art von Filterung durch die API durchführen zu lassen. Sie müssen dies also selbst tun, aber in Ihrem speziellen Fall müssen Sie nicht das gesamte Verzeichnis aufzählen. Sie können zumindest die API tun, die es filtern kann tun, und dann tun Sie Ihre eigenen Filterung darüber.

EDIT: Wenn Sie benötigen, um sicherzustellen, dass die drei Zeichen nach der „a“ Ziffern sind, können Sie es auf diese Weise tun:

if (length(tsrMessage.Name)=8) and tsrMessage[2].IsDigit and tsrMessage[3].IsDigit and tsrMessage[4].IsDigit then ShowMessage(tsrMessage.Name); 

sofern Sie einen modernen Compiler verwenden (Sie müssen enthält die "Zeichen" -Einheit). Beachten Sie auch, dass Sie, wenn Sie eine mobile Version kompilieren, stattdessen index [1], [2] und [3] verwenden müssen, da sie den Index bei 0 für Strings starten.

Wenn Sie eine ältere Version verwenden, können Sie es wie folgt tun:

function IsDigit(c : char) : boolean; 
    begin 
    Result:=(c>='0') and (c<='9') 
    end; 

if (length(tsrMessage.Name)=8) and IsDigit(tsrMessage[2]) and IsDigit(tsrMessage[3]) and IsDigit(tsrMessage[4]) then ShowMessage(tsrMessage.Name); 
+0

Ja, ich wollte diese Methode auch verwenden, aber das von mir verwendete Beispiel wurde vereinfacht. Eigentlich muss ich Dateien nach Maske wie im Format% 03d.txt usw. löschen. In diesem Fall wird der Code für solch eine einfache Aufgabe zu kompliziert, so dass ich entschied, dass ich etwas falsch mache. – Molochnik

+0

@Molotechnik: Siehe EDIT-Sektion ... – HeartWare

4

Dieses Verhalten ist wie vorgesehen. Es wird von Raymond Chen hier erklärt: How did wildcards work in MS-DOS?

Sie sehen das gleiche Verhalten von der Befehlsinterpreter.

 
C:\Desktop>dir a???.txt 
Volume in drive C has no label. 
Volume Serial Number is 20DA-7FEB 

Directory of C:\Desktop 

26/06/2016 14:03     6 a.txt 
26/06/2016 14:03     6 a1.txt 
26/06/2016 14:03     6 a12.txt 
26/06/2016 14:03     6 a123.txt 
       4 File(s)    24 bytes 
       0 Dir(s) 286,381,445,120 bytes free 

Es gibt keine Möglichkeit FindFirstFile (die API, die hinter dem RTL-FindFirst unter Windows ist) davon zu überzeugen, wie Sie wollen verhalten. Die beste Option ist das Auflisten des gesamten Verzeichnisses und die Durchführung einer eigenen Filterung mit dem von Ihnen gewählten Mustervergleichsalgorithmus.

+0

Danke, habe es, es war diese Wildcard lange Zeit, da ich das letzte Mal verwendet, so kann ich 100% sicher war, dass „?“ bedeutet genau ein Zeichen. – Molochnik

+0

@Molochnik Der einzelne Platzhalter für Zeichen in SQL funktioniert genau so, wie Sie es beschreiben - vielleicht kommt Ihre Verwirrung daher. Es hat mich schon früher erwischt. Grüße, –

+0

@Michael Ja, das ist möglich, aber unwahrscheinlich, seit einem Jahrzehnt benutze ich reguläre Ausdrücke (früher benutzte ich fnmatch) und es kam mir nicht in den Sinn, dass es immer noch Regulars ohne einen Platzhalter gibt, der a bedeutet einzelnes Zeichen. – Molochnik