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
*)