How to sort a list of files by name, extension, dates, and size in Pascal

1 Answer

0 votes
program FileSorter;

{$mode objfpc}{$H+}

uses
  SysUtils, Classes;

(* ------------------------------------------------------------ *)
(* Date struct for proper date handling                         *)
(* ------------------------------------------------------------ *)
type
  TDate = record
    year  : Integer;
    month : Integer;
    day   : Integer;
  end;

(* ------------------------------------------------------------ *)
(* File entry struct                                            *)
(* ------------------------------------------------------------ *)
type
  TFileEntry = record
    name      : String;   (* file name without extension *)
    extension : String;   (* extension including dot *)
    date      : TDate;    (* real date struct *)
    size      : Integer;  (* bytes *)
  end;

  PFileEntry = ^TFileEntry;

(* Global array of files *)
var
  Files: array of TFileEntry;

(* ------------------------------------------------------------ *)
(* Print a date in YYYY-MM-DD format                            *)
(* ------------------------------------------------------------ *)
function FormatDate(const d: TDate): String;
begin
  Result := Format('%4d-%0.2d-%0.2d', [d.year, d.month, d.day]); 
end;

(* ------------------------------------------------------------ *)
(* Sort by name (lexicographically)                             *)
(* ------------------------------------------------------------ *)
function CompareByName(List: TStringList; Index1, Index2: Integer): Integer;
var
  a, b: PFileEntry;
begin
  a := PFileEntry(List.Objects[Index1]);
  b := PFileEntry(List.Objects[Index2]);
  Result := CompareStr(a^.name, b^.name);
end;

(* ------------------------------------------------------------ *)
(* Sort by extension (lexicographically)                        *)
(* ------------------------------------------------------------ *)
function CompareByExtension(List: TStringList; Index1, Index2: Integer): Integer;
var
  a, b: PFileEntry;
begin
  a := PFileEntry(List.Objects[Index1]);
  b := PFileEntry(List.Objects[Index2]);
  Result := CompareStr(a^.extension, b^.extension);
end;

(* ------------------------------------------------------------ *)
(* Sort by date (year → month → day)                            *)
(* ------------------------------------------------------------ *)
function CompareByDate(List: TStringList; Index1, Index2: Integer): Integer;
var
  a, b: PFileEntry;
begin
  a := PFileEntry(List.Objects[Index1]);
  b := PFileEntry(List.Objects[Index2]);

  if a^.date.year <> b^.date.year then
    Exit(a^.date.year - b^.date.year);

  if a^.date.month <> b^.date.month then
    Exit(a^.date.month - b^.date.month);

  Result := a^.date.day - b^.date.day;
end;

(* ------------------------------------------------------------ *)
(* Sort by size (ascending)                                     *)
(* ------------------------------------------------------------ *)
function CompareBySize(List: TStringList; Index1, Index2: Integer): Integer;
var
  a, b: PFileEntry;
begin
  a := PFileEntry(List.Objects[Index1]);
  b := PFileEntry(List.Objects[Index2]);
  Result := a^.size - b^.size;
end;

(* ------------------------------------------------------------ *)
(* Print file list                                              *)
(* ------------------------------------------------------------ *)
procedure PrintFiles;
var
  i: Integer;
begin
  for i := 0 to High(Files) do
    WriteLn(Files[i].name, Files[i].extension, '  ',
            FormatDate(Files[i].date), '  ',
            Files[i].size, ' bytes');
  WriteLn;
end;

(* Convert array to sortable TStringList *)
function ToList: TStringList;
var
  i: Integer;
  p: PFileEntry;
begin
  Result := TStringList.Create;
  for i := 0 to High(Files) do
  begin
    New(p);
    p^ := Files[i];
    Result.AddObject('', TObject(p));
  end;
end;

(* Convert TStringList back to array *)
procedure FromList(L: TStringList);
var
  i: Integer;
begin
  for i := 0 to High(Files) do
    Files[i] := PFileEntry(L.Objects[i])^;
end;

(* Free pointers stored in list *)
procedure FreeListObjects(L: TStringList);
var
  i: Integer;
begin
  for i := 0 to L.Count - 1 do
    Dispose(PFileEntry(L.Objects[i]));
end;

var
  L: TStringList;

begin
  SetLength(Files, 10);

  Files[0].name      := 'G1zTo5jJk';
  Files[0].extension := '.jpg';
  Files[0].date.year := 2007; Files[0].date.month := 7; Files[0].date.day := 8;
  Files[0].size      := 51954;

  Files[1].name      := 'LTEE4SI0j';
  Files[1].extension := '.jpg';
  Files[1].date.year := 2011; Files[1].date.month := 11; Files[1].date.day := 13;
  Files[1].size      := 43442;

  Files[2].name      := 'PDqmuO3GH';
  Files[2].extension := '.cpp';
  Files[2].date.year := 2004; Files[2].date.month := 5; Files[2].date.day := 21;
  Files[2].size      := 3346;

  Files[3].name      := 'qJO2qjukZ';
  Files[3].extension := '.png';
  Files[3].date.year := 2010; Files[3].date.month := 8; Files[3].date.day := 27;
  Files[3].size      := 67087;

  Files[4].name      := 'HqclTqxb4';
  Files[4].extension := '.cpp';
  Files[4].date.year := 2020; Files[4].date.month := 9; Files[4].date.day := 5;
  Files[4].size      := 70531;

  Files[5].name      := 'imVyTyoaF';
  Files[5].extension := '.jpg';
  Files[5].date.year := 2011; Files[5].date.month := 3; Files[5].date.day := 19;
  Files[5].size      := 43846;

  Files[6].name      := 'rXwXdy8XO';
  Files[6].extension := '.txt';
  Files[6].date.year := 2017; Files[6].date.month := 10; Files[6].date.day := 12;
  Files[6].size      := 70193;

  Files[7].name      := '9Z4fbOBUc';
  Files[7].extension := '.pdf';
  Files[7].date.year := 2004; Files[7].date.month := 6; Files[7].date.day := 9;
  Files[7].size      := 1754;

  Files[8].name      := 'ZHahuu4vS';
  Files[8].extension := '.txt';
  Files[8].date.year := 2003; Files[8].date.month := 10; Files[8].date.day := 10;
  Files[8].size      := 65126;

  Files[9].name      := '0SnZHh2GT';
  Files[9].extension := '.png';
  Files[9].date.year := 2006; Files[9].date.month := 10; Files[9].date.day := 18;
  Files[9].size      := 25890;

  WriteLn('Original:');
  PrintFiles;

  WriteLn('Sorted by name:');
  L := ToList;
  L.CustomSort(@CompareByName);
  FromList(L);
  FreeListObjects(L);
  L.Free;
  PrintFiles;

  WriteLn('Sorted by extension:');
  L := ToList;
  L.CustomSort(@CompareByExtension);
  FromList(L);
  FreeListObjects(L);
  L.Free;
  PrintFiles;

  WriteLn('Sorted by date:');
  L := ToList;
  L.CustomSort(@CompareByDate);
  FromList(L);
  FreeListObjects(L);
  L.Free;
  PrintFiles;

  WriteLn('Sorted by size:');
  L := ToList;
  L.CustomSort(@CompareBySize);
  FromList(L);
  FreeListObjects(L);
  L.Free;
  PrintFiles;
end.



(*
run:

Original:
G1zTo5jJk.jpg  2007-07-08  51954 bytes
LTEE4SI0j.jpg  2011-11-13  43442 bytes
PDqmuO3GH.cpp  2004-05-21  3346 bytes
qJO2qjukZ.png  2010-08-27  67087 bytes
HqclTqxb4.cpp  2020-09-05  70531 bytes
imVyTyoaF.jpg  2011-03-19  43846 bytes
rXwXdy8XO.txt  2017-10-12  70193 bytes
9Z4fbOBUc.pdf  2004-06-09  1754 bytes
ZHahuu4vS.txt  2003-10-10  65126 bytes
0SnZHh2GT.png  2006-10-18  25890 bytes

Sorted by name:
0SnZHh2GT.png  2006-10-18  25890 bytes
9Z4fbOBUc.pdf  2004-06-09  1754 bytes
G1zTo5jJk.jpg  2007-07-08  51954 bytes
HqclTqxb4.cpp  2020-09-05  70531 bytes
LTEE4SI0j.jpg  2011-11-13  43442 bytes
PDqmuO3GH.cpp  2004-05-21  3346 bytes
ZHahuu4vS.txt  2003-10-10  65126 bytes
imVyTyoaF.jpg  2011-03-19  43846 bytes
qJO2qjukZ.png  2010-08-27  67087 bytes
rXwXdy8XO.txt  2017-10-12  70193 bytes

Sorted by extension:
HqclTqxb4.cpp  2020-09-05  70531 bytes
PDqmuO3GH.cpp  2004-05-21  3346 bytes
LTEE4SI0j.jpg  2011-11-13  43442 bytes
imVyTyoaF.jpg  2011-03-19  43846 bytes
G1zTo5jJk.jpg  2007-07-08  51954 bytes
9Z4fbOBUc.pdf  2004-06-09  1754 bytes
qJO2qjukZ.png  2010-08-27  67087 bytes
0SnZHh2GT.png  2006-10-18  25890 bytes
rXwXdy8XO.txt  2017-10-12  70193 bytes
ZHahuu4vS.txt  2003-10-10  65126 bytes

Sorted by date:
ZHahuu4vS.txt  2003-10-10  65126 bytes
PDqmuO3GH.cpp  2004-05-21  3346 bytes
9Z4fbOBUc.pdf  2004-06-09  1754 bytes
0SnZHh2GT.png  2006-10-18  25890 bytes
G1zTo5jJk.jpg  2007-07-08  51954 bytes
qJO2qjukZ.png  2010-08-27  67087 bytes
imVyTyoaF.jpg  2011-03-19  43846 bytes
LTEE4SI0j.jpg  2011-11-13  43442 bytes
rXwXdy8XO.txt  2017-10-12  70193 bytes
HqclTqxb4.cpp  2020-09-05  70531 bytes

Sorted by size:
9Z4fbOBUc.pdf  2004-06-09  1754 bytes
PDqmuO3GH.cpp  2004-05-21  3346 bytes
0SnZHh2GT.png  2006-10-18  25890 bytes
LTEE4SI0j.jpg  2011-11-13  43442 bytes
imVyTyoaF.jpg  2011-03-19  43846 bytes
G1zTo5jJk.jpg  2007-07-08  51954 bytes
ZHahuu4vS.txt  2003-10-10  65126 bytes
qJO2qjukZ.png  2010-08-27  67087 bytes
rXwXdy8XO.txt  2017-10-12  70193 bytes
HqclTqxb4.cpp  2020-09-05  70531 bytes

*)

 



answered 1 day ago by avibootz
edited 1 day ago by avibootz

Related questions

...