0

我需要删除所有以“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;

我一直以为问号的意思是一个且只有一个字符,但出乎我意料的是,这段代码返回的是“a.txt”、“a1.txt”和“a123.txt”文件名。有没有一种简单的方法可以修改代码以仅查找“a123.txt”之类的文件?

4

2 回答 2

4

满足您特定需求的最简单解决方案是替换它:

ShowMessage(tsrMessage.Name);

有了这个

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

这将确保文件名的长度正好是四个字符 + 句点 + 扩展名。就像大卫说的那样,没有办法让 API 进行这种过滤,所以你必须自己做,但在你的特定情况下,没有必要枚举整个目录。你至少可以让 API 做它可以做的过滤,然后在它上面做你自己的过滤。

编辑:如果您需要确保“a”后面的三个字符是数字,您可以这样做:

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

前提是您使用的是现代编译器(您需要包含“字符”单元)。另请注意,如果您正在编译移动版本,则需要使用索引 [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);
于 2016-06-26T16:05:55.983 回答
4

此行为符合设计。Raymond Chen 在这里解释了这一点:通配符在 MS-DOS 中是如何工作的?

您将从命令解释器中看到完全相同的行为。

C:\Desktop>dir a???.txt
 驱动器 C 中的卷没有标签。
 卷序列号为 20DA-7FEB

 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 个文件 24 字节
               0 Dir(s) 286,381,445,120 字节空闲

没有办法说服FindFirstFile(Windows 上 RTL 背后的 API FindFirst)按照您希望的方式行事。您最好的选择是枚举整个目录,并使用您选择的模式匹配算法执行您自己的过滤。

于 2016-06-26T13:06:56.347 回答