我需要删除所有文件,这些文件的名称以" a"开头,然后是三个任意字母和" .txt"扩展名如" a123.txt"。这是代码:
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;
我一直认为问号意味着一个且只有一个字符,但令我惊讶的是,这个代码返回&#34; a.txt&#34;,&#34; a1.txt&#34;和&#34; a123.txt&#34;文件名。是否有一种简单的方法可以修改代码,只搜索&#34; a123.txt&#34;等文件?
答案 0 :(得分:4)
此行为与设计完全相同。 Raymond Chen在此解释:How did wildcards work in MS-DOS?
您将从命令解释程序中看到完全相同的行为。
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
无法说服FindFirstFile
(Windows上RTL&lt; FindFirst
背后的API)按照您的意愿行事。您最好的选择是枚举整个目录,并使用您选择的模式匹配算法执行自己的过滤。
答案 1 :(得分:4)
满足您特定需求的最简单的解决方案是替换它:
ShowMessage(tsrMessage.Name);
用这个
if length(tsrMessage.Name)=8 then ShowMessage(tsrMessage.Name);
这将确保文件名的长度恰好是四个字符+句点+扩展名。就像David说的那样,没有办法让API进行这种过滤,所以你必须自己做,但在你的特定情况下,没有必要枚举整个目录。您至少可以让API执行可以做的过滤,然后在其上进行自己的过滤。
编辑:如果你需要确保&#34; a&#34;之后的三个字符。是数字,你可以这样做:
if (length(tsrMessage.Name)=8) and tsrMessage[2].IsDigit and tsrMessage[3].IsDigit and tsrMessage[4].IsDigit then ShowMessage(tsrMessage.Name);
如果您使用的是现代编译器(您需要包含&#34; Characters&#34;单元)。另请注意,如果您正在编译移动版本,则需要使用索引[1],[2]和[3],因为它们在字符串的0处开始索引。
如果您使用的是旧版本,可以这样做:
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);