Search only files that match part of the name in a directory

Asked

Viewed 1,263 times

2

I have the following problem

In a given directory I will need to create files that meet the following criteria.

DOCUMENTO_DDMM_SEQ.txt

Where

  • Document : Any number that may or may not be repeated
  • DDMM : Day + Month of current date
  • SEQ : Global Directory Sequence Starting at 001

In order to generate the correct sequence I need to know the value of the last sequence (higher value)

I was able to approach reading all the files from the directory to a list and iterating the list in search of the last value, but this method is very bad, because the directory is the user’s choice and it can use a directory that contains many files, making this research very slow. Wanted something that already filtered the files before I had to iterate the list.

Any suggestion will be evaluated

  • 1º - How will the user choose the directory ? I will start working on a response!

  • I am using Unit Filectrl’s Selectdirectory method after I use the File class to recover the list of files, and this list looks at the file names. I’m testing a code using Tsearchrec. I think it’s the way.

1 answer

1


I was able to do what I wanted using Tsearchrec as follows.

procedure TFrm....
  var search : TSearchRec; // Unit SysUtils
    filename, dirname : String;
    seq, i : Integer;
Begin
  // (...)
  if not SelectDirectory('Selecione o diretório', 'arqs', dirname) then // Unit FileCtrl
    begin
       Application.MessageBox('Sem destino', APPNAME, MB_OK+MB_ICONERROR);
       Exit;
    end;
  try 
    // Pesquisando o diretório corrente para gerar arquivos únicos
    if (FindFirst(dirname + '*_' + FormatDateTime('ddmm', Date) + '_*.txt',
                    faArchive,
                    searchResult) = 0 ) then
      begin
        repeat
          // Extraindo o sequencial do arquivo
          i := LastDelimiter('_', searchResult.Name);
          if (TryStrToInt(copy(searchResult.Name, i, 3), i)) then
            seq := Max(i, seq);
        until FindNext(searchResult) <> 0;
        FindClose(searchResult);
      end;

    filename := NUMERO_DOCUMENTO + '_' +
                FormatDateTime('ddmm', Date) + '_' +
                LPad(IntToStr(seq + 1), 3, '0') + '.txt'; // LPad função privada de padding à esquerda
    // Garantindo que não existe arquivo com a nomenclatura passada
    while FileExists(dirname + filename) do
      begin
        seq := seq + 1;
        filename := NUMERO_DOCUMENTO  + '_' +
                    FormatDateTime('ddmm', Date) + '_' +
                    LPad(IntToStr(seq + 1), 3, '0') + '.txt';

      end;  

    // (Outros códigos ...)
End;
End.

One thing that helped me with this code was the use of TryStrToInt, because it allowed me to prevent an unfinished name in _999.txt from causing the application to generate a Exception conversion.

Apparently I could have problems when the sequence arrived in 999 because the next one to be generated would be _1000.txt and instead of being able to fetch the value 1000, as I am limiting to 3 characters will end up picking 100 and iterating in the existence check until the 1001. It’ll work out the wrong way.

A solution would be to find the position of ". txt" to calculate the number of characters to be used for both the function copy how much for the padding.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.