Recent

Author Topic: FindAllFiles does not include empty Directories and Mask weirdness  (Read 5248 times)

QEnnay

  • Full Member
  • ***
  • Posts: 115
Hi,

Just discovered why some backups where not being done correctly.

Code: Pascal  [Select][+][-]
  1. var
  2.   slFilesFrom : TStringList;
  3.   begin
  4.     slFilesFrom:=TSringList.Create;
  5.     FindAllFiles(slFilesFrom,fldFrom,'*', subdirsYes, faAnyFileYes);
  6.  

Using the Mask as "*.*" only gets files with an Extension and skips all files **without** an Extension.

It also ignores empty Folders, which is technically a File anyway as the Attribute in the original Procedure Declaration shows,

Code: Pascal  [Select][+][-]
  1. procedure FindAllFiles(AList: TStrings; const SearchPath: String;
  2.   SearchMask: String = ''; SearchSubDirs: Boolean = True; DirAttr: Word = faDirectory); overload;
  3.  

Isn't that implying that Directories are Files too when I use the Attribute faAnyFile?

OK, so how do I gather all files and folders, empty or otherwise, Extension or not?

Thanks
Linux-Mint 20.1 x64 + Cinnamon; Lenovo Flex 5 Ryzen 5 4500, 16GB memory
FPC: 3.2.0-1, Lazarus 2.0.12-0, all 64bit

pcurtis

  • Hero Member
  • *****
  • Posts: 951
Re: FindAllFiles does not include empty Directories and Mask weirdness
« Reply #1 on: October 13, 2021, 07:22:25 pm »
Does FindFirst, FindNext, FindClose work on Linux?
Windows 10 20H2
Laz 2.2.0
FPC 3.2.2

QEnnay

  • Full Member
  • ***
  • Posts: 115
Re: FindAllFiles does not include empty Directories and Mask weirdness
« Reply #2 on: October 13, 2021, 07:34:41 pm »
Does FindFirst, FindNext, FindClose work on Linux?

Thanks, yes, but I was hoping I did not have to write a Recursive File and Directory gathering routine when one is already there -- well kinda there. :)
Linux-Mint 20.1 x64 + Cinnamon; Lenovo Flex 5 Ryzen 5 4500, 16GB memory
FPC: 3.2.0-1, Lazarus 2.0.12-0, all 64bit

winni

  • Hero Member
  • *****
  • Posts: 3197
Re: FindAllFiles does not include empty Directories and Mask weirdness
« Reply #3 on: October 13, 2021, 07:40:32 pm »
Hi,

Just discovered why some backups where not being done correctly.

Using the Mask as "*.*" only gets files with an Extension and skips all files **without** an Extension.


Hi!

Thats not true. It ignores all files without a dot - as you instructed by *.*

Yes - directories are included if you uses faAnyfile

Winni

QEnnay

  • Full Member
  • ***
  • Posts: 115
Re: FindAllFiles does not include empty Directories and Mask weirdness
« Reply #4 on: October 13, 2021, 08:45:22 pm »

Yes - directories are included if you uses faAnyfile

That would be nice to think so, but did you actually try it? IF the Directory is empty it is NOT included.

Moot now, I found some code (http://www.festra.com/eng/snip04.htm) and Linux-ized plus a tweak or two and it and it is now returning **ALL** Files.

If anyone ever needs it, here ya go.
Code: Pascal  [Select][+][-]
  1.  
  2. unit u_findAllFiles;
  3.  
  4. {$mode objfpc}{$H+}
  5.  
  6. interface
  7.  
  8. uses
  9.   Classes, SysUtils, Forms, Controls, Graphics, Dialogs, StdCtrls;
  10.  
  11. type
  12.  
  13.   { TfrmFileFind }
  14.  
  15.   TfrmFileFind = class(TForm)
  16.     Button1: TButton;
  17.     edPath: TEdit;
  18.     lblCount: TLabel;
  19.     lbFiles: TListBox;
  20.     procedure Button1Click(Sender: TObject);
  21.   private
  22.  
  23.   public
  24.     procedure exFindAllFiles(FilesList : TStringList; StartDir, FileMask : string);
  25.   end;
  26.  
  27. var
  28.   frmFileFind : TfrmFileFind;
  29.  
  30. implementation
  31.  
  32. {$R *.lfm}
  33.  
  34. procedure TfrmFileFind.exFindAllFiles(FilesList: TStringList; StartDir, FileMask: string);
  35. var
  36.   SR : TSearchRec;
  37.   DirList : TStringList;
  38.   IsFound : Boolean;
  39.   i : integer;
  40. begin
  41.   { Build a list of the files in directory StartDir!) }
  42.   IsFound:=FindFirst(StartDir+FileMask,faAnyFile,SR) = 0;
  43.   while IsFound do
  44.   begin
  45.     if (Pos('/.',SR.name) = 0 ) and
  46.        (SR.Name[1] <> '.') then
  47.     begin
  48.       FilesList.Add(StartDir+SR.Name);
  49.     end;
  50.     IsFound:=FindNext(SR) = 0;
  51.   end;
  52.   FindClose(SR);
  53.  
  54.   // Build a list of subdirectories
  55.   DirList:=TStringList.Create;
  56.   IsFound:=FindFirst(StartDir+Filemask,faAnyFile,SR) = 0;
  57.   while IsFound do
  58.   begin
  59.     if ((SR.Attr and faDirectory) <> 0) and
  60.        (SR.Name[1] <> '.') and
  61.        (Pos('/.',SR.name) = 0 ) then
  62.          DirList.Add(StartDir+SR.Name+'/');
  63.     IsFound:=FindNext(SR) = 0;
  64.   end;
  65.   FindClose(SR);
  66.  
  67.   // Scan the list of subdirectories
  68.   for i:=0 to DirList.Count - 1 do
  69.   begin
  70.     exFindAllFiles(FilesList,DirList[i], FileMask);
  71.   end;
  72.  
  73.   DirList.Free;
  74. end;
  75.  
  76. { TfrmFileFind }
  77.  
  78. procedure TfrmFileFind.Button1Click(Sender: TObject);
  79. // Example: how to use exFindFiles
  80. var
  81.   FilesList : TStringList;
  82. begin
  83.   FilesList:=TStringList.Create;
  84.   try
  85.     exFindAllFiles(FilesList,edPath.Text,'*');
  86.     lbFiles.Items.Assign(FilesList);
  87.     LblCount.Caption:='Files found: '+IntToStr(FilesList.Count);
  88.   finally
  89.     FilesList.Free;
  90.   end;
  91. end;
  92.  
  93. end.
  94.  
Linux-Mint 20.1 x64 + Cinnamon; Lenovo Flex 5 Ryzen 5 4500, 16GB memory
FPC: 3.2.0-1, Lazarus 2.0.12-0, all 64bit

winni

  • Hero Member
  • *****
  • Posts: 3197
Re: FindAllFiles does not include empty Directories and Mask weirdness
« Reply #5 on: October 13, 2021, 08:50:29 pm »

That would be nice to think so, but did you actually try it? IF the Directory is empty it is NOT included.

Moot now, I found some code (http://www.festra.com/eng/snip04.htm) and Linux-ized p


Hi

That is intended. Look in the code. As the names says:

FindAllFiles finds all files.  Not empty directories.

For searching for all drectories there is the procedure findAllDirectories

Winni

« Last Edit: October 13, 2021, 08:52:27 pm by winni »

QEnnay

  • Full Member
  • ***
  • Posts: 115
Re: FindAllFiles does not include empty Directories and Mask weirdness
« Reply #6 on: October 13, 2021, 10:21:24 pm »
{sigh} I give up.
Linux-Mint 20.1 x64 + Cinnamon; Lenovo Flex 5 Ryzen 5 4500, 16GB memory
FPC: 3.2.0-1, Lazarus 2.0.12-0, all 64bit

Bart

  • Hero Member
  • *****
  • Posts: 5275
    • Bart en Mariska's Webstek
Re: FindAllFiles does not include empty Directories and Mask weirdness
« Reply #7 on: October 13, 2021, 11:21:51 pm »
FindAllFiles is a convenience routine.
If it does not suit your needs, then either extend it for your own purposes (in your case, might be easy), or build something that actually does what you want.
There have been umerous proposals to add more and more options, to make it a kind of Swiss army-knive.

We won't do that.

FindAllFiles is most likely not versatile enough if you need it to make backups.
My own backup program uses it's own class to find all files and all directories and has callbacks to add process what it finds.

Just one other remark: '*.*' will find all files on DOS/Windows based systems, but on *nix '*.*' means zero or more characters of any kind followed by a dot followed by zero or more characters of any kind. So it will match '.', '.foo', 'bar.foo', but it won't match 'foo'.
That is why we have the AllFilesMask constant in the system unit.
This works on all supportes operating systems.

Bart

QEnnay

  • Full Member
  • ***
  • Posts: 115
Re: FindAllFiles does not include empty Directories and Mask weirdness
« Reply #8 on: October 17, 2021, 04:55:17 pm »
FindAllFiles is a convenience routine.
If it does not suit your needs, then either extend it for your own purposes (in your case, might be easy), or build something that actually does what you want.

Then it should be called "FindMostFiles" or "FindSomeFiles" or "FindAllFilesInWindows" as it certainly does **not** find all files in Linux.

There have been umerous proposals to add more and more options, to make it a kind of Swiss army-knive.

Not looking for a swiss-anything, just a routine that does what it says it will do, find **all** files.

My own backup program uses it's own class to find all files and all directories and has callbacks to add process what it finds.

Instead of chest thumping, it might be a nice gesture to share at least a small portion of that Search code to help others to actually find **all** files in Linux.

That is why we have the AllFilesMask constant in the system unit.

Well, that is nonsense, the "AllFilesMask" is still only defined as a single Asterisk in System-Unit which does not work any differently.
Here are some facts for Linux and FindSomeFiles(

Mask '*.*" finds 3-files in my test directory Tree.
Mask '*" finds 67-files in my test directory Tree.
Mask 'AllFilesMask" finds 67-files in my test directory Tree.

Using the File manager of Ubuntu it shows 75-files, clearly some of those re Directories, but FindAllFiles it ain't.

Thanks for nothing.
Linux-Mint 20.1 x64 + Cinnamon; Lenovo Flex 5 Ryzen 5 4500, 16GB memory
FPC: 3.2.0-1, Lazarus 2.0.12-0, all 64bit

PascalDragon

  • Hero Member
  • *****
  • Posts: 5446
  • Compiler Developer
Re: FindAllFiles does not include empty Directories and Mask weirdness
« Reply #9 on: October 18, 2021, 01:38:16 pm »
FindAllFiles is a convenience routine.
If it does not suit your needs, then either extend it for your own purposes (in your case, might be easy), or build something that actually does what you want.

Then it should be called "FindMostFiles" or "FindSomeFiles" or "FindAllFilesInWindows" as it certainly does **not** find all files in Linux.

Directories are not considered files in Pascal, thus FindAllFiles is correct.

Bart

  • Hero Member
  • *****
  • Posts: 5275
    • Bart en Mariska's Webstek
Re: FindAllFiles does not include empty Directories and Mask weirdness
« Reply #10 on: October 18, 2021, 10:32:24 pm »
My own backup program uses it's own class to find all files and all directories and has callbacks to add process what it finds.

Instead of chest thumping, it might be a nice gesture to share at least a small portion of that Search code to help others to actually find **all** files in Linux.

Well, my backup program and all code it uses can be found at https://svn.code.sf.net/p/flyingsheep/code/trunk/. It's all LGPL, so use, modify as you see fit.


That is why we have the AllFilesMask constant in the system unit.

Well, that is nonsense, the "AllFilesMask" is still only defined as a single Asterisk in System-Unit which does not work any differently.

I was trying to explain that '*.*' is not the appropriate mask for all files on your system.
While this works on Windows, it does not on *nix.
The AllFilesMask is defined per OS and works for that OS, so when you use AllFilesMask your code will be cross platform.
(B.t.w. '*' works on Windows as well, hence AllFilesMask is '*' on Windows as well.)

And of course on your platform AllFilesMask works exactlly like '*', because it is defined as '*' on *nix (because that is the appropriate mask). If you use FindFirst/FindNext with the correct attribute set, then it will report all files and folders.
FindAllFiles by design only returns files, not folders.

If you look at the code of FindAllFiles you can see the engine it uses.
That same engine can be used in a different way to return all files and folders IIRC it has OnFileFound and OnDirectoryFound events that you can use to do what you want.

Bart

winni

  • Hero Member
  • *****
  • Posts: 3197
Re: FindAllFiles does not include empty Directories and Mask weirdness
« Reply #11 on: October 18, 2021, 11:14:56 pm »
Hi!

What QEnnay desperatly needs is

* FindAllFiles
* FindAllDirectories
* Add the  two StringLists
* Sort

That's the whole secret.

Plus an understanding of  the FileMask mentioned above.


Winni

Bart

  • Hero Member
  • *****
  • Posts: 5275
    • Bart en Mariska's Webstek
Re: FindAllFiles does not include empty Directories and Mask weirdness
« Reply #12 on: October 19, 2021, 04:00:25 pm »
Hmm, running FindAllFiles and after that FindAllDirectories would wordk, but why iterate the whole tree twice?

Bart

 

TinyPortal © 2005-2018