2016-06-26 2 views
0

"a"로 시작하고 3 개의 임의 문자 및 "a123.txt"와 같은 ".txt"확장자로 시작하는 모든 파일을 삭제해야합니다. 여기 코드는 다음과 같습니다FindFirst 및 물음표

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

사용자의 특정 요구에 대한 간단한 솔루션이를 대체하는 것입니다 확장자. David가 말했듯이, API가 이런 종류의 필터링을 수행하는 방법은 없기 때문에 직접해야만합니다. 그러나 특별한 경우에는 전체 디렉토리를 열거 할 필요가 없습니다. 적어도 API가 필터링을 수행하도록 할 수 있습니다. 을 수행 한 다음 필터링을 수행하십시오.

편집 : 당신은 세 개의 문자가 "A"숫자는, 당신이 그것을 할 수있는이 방법으로 다음과 같은 것을 보장해야하는 경우 :

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

당신이 현대 컴파일러를 사용하고 제공을 (당신은해야합니다 "Characters"단위 포함). 또한 모바일 버전을 컴파일하는 경우 인덱스 [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); 
+0

예이 방법을 사용하고 싶었지만 사용했던 예제가 단순화되었습니다. 실제로 % 03d.txt 등의 형식에서와 같이 마스크에 따라 파일을 삭제해야합니다.이 경우 코드가 이러한 간단한 작업에 너무 복잡해져서 내가 잘못한 것을 결정했습니다. – Molochnik

+0

@Molochnik : 편집 섹션 참조 ... – HeartWare

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합니다 (RTL의 FindFirst Windows에서 뒤에있는 API)를 설득 할 수있는 방법이 없습니다. 최선의 선택은 전체 디렉토리를 열거하고 선택한 패턴 매칭 알고리즘을 사용하여 자신의 필터링을 수행하는 것입니다. + 파일 이름의 길이는 정확히 네 문자 + 기간 있는지 확인합니다이

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

이 함께

ShowMessage(tsrMessage.Name); 

:

+0

덕분에, 내가 그 100 % 확신했다, 그래서 나는 마지막으로이 와일드 카드를 사용하기 때문에 오랜 시간이 지났있어 "?" 정확히 한 문자를 의미합니다. – Molochnik

+0

@Molochnik SQL의 단일 문자 와일드 카드는 설명하는대로 작동합니다. 아마도 혼란이 어디에서오고 있는지 알 수 있습니다. 그것 전에 나를 붙 잡았다. 감사합니다, –

+0

@Michael 그렇습니다. 가능 합니다만, 10 년 동안 정규 표현식 표기법 (이전에 fnmatch를 사용했습니다)을 사용하여 와일드 카드를 사용하지 않은 정규 표현식이 여전히 존재한다는 것을 알지 못했습니다. 단일 문자. – Molochnik