delp.pp 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307
  1. {
  2. Copyright (c) 1999-2012 by Peter Vreman, Michael Van Canneyt
  3. Deletes all files generated for Pascal (*.exe,units,objects,libs)
  4. This program is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published by
  6. the Free Software Foundation; either version 2 of the License, or
  7. (at your option) any later version.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with this program; if not, write to the Free Software
  14. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  15. ****************************************************************************}
  16. program Delp;
  17. {$mode ObjFPC}{$H+}
  18. uses
  19. Sysutils,getopts;
  20. const
  21. Version = 'Version 1.3';
  22. Title = 'DelPascal';
  23. Copyright = 'Copyright (c) 1999-2012 by the Free Pascal Development Team';
  24. function DStr(l:longint):string;
  25. var
  26. TmpStr : string[32];
  27. i : byte;
  28. begin
  29. Str(l,tmpstr);
  30. i:=Length(TmpStr);
  31. while (i>3) do
  32. begin
  33. i:=i-3;
  34. if TmpStr[i]<>'-' then
  35. Insert('.',TmpStr,i+1);
  36. end;
  37. DStr:=TmpStr;
  38. end;
  39. procedure dosfsplit(path:ansistring;var dir,name,ext:ansistring);
  40. // implementation of dos.fsplit on top of sysutils routines to avoid
  41. // path length issues.
  42. // a lot of old tooling uses fsplit, maybe move this to sysutils?
  43. begin
  44. dir:=extractfiledir(dir);
  45. name:=changefileext(extractfilename(path),'');
  46. ext:=extractfileext(path);
  47. if (length(ext)>0) and (ext[1]='.') then
  48. delete(ext,1,1);
  49. end;
  50. function MatchesMask(What, Mask: string): boolean;
  51. Function CmpStr(const hstr1,hstr2:string):boolean;
  52. var
  53. found : boolean;
  54. i1,i2 : longint;
  55. begin
  56. i1:=0;
  57. i2:=0;
  58. found:=true;
  59. while found and (i1<length(hstr1)) and (i2<length(hstr2)) do
  60. begin
  61. inc(i2);
  62. inc(i1);
  63. case hstr1[i1] of
  64. '?' :
  65. found:=true;
  66. '*' :
  67. begin
  68. found:=true;
  69. if (i1=length(hstr1)) then
  70. i2:=length(hstr2)
  71. else
  72. if (i1<length(hstr1)) and (hstr1[i1+1]<>hstr2[i2]) then
  73. begin
  74. if i2<length(hstr2) then
  75. dec(i1)
  76. end
  77. else
  78. if i2>1 then
  79. dec(i2);
  80. end;
  81. else
  82. found:=(hstr1[i1]=hstr2[i2]) or (hstr2[i2]='?');
  83. end;
  84. end;
  85. if found then
  86. begin
  87. { allow 'p*' matching 'p' }
  88. if (i1<length(hstr1)) and (hstr1[i1+1]='*') then
  89. inc(i1);
  90. found:=(i1>=length(hstr1)) and (i2>=length(hstr2));
  91. end;
  92. CmpStr:=found;
  93. end;
  94. var
  95. D1,D2 : ansistring;
  96. N1,N2 : ansistring;
  97. E1,E2 : ansistring;
  98. begin
  99. {$ifdef Unix}
  100. DosFSplit(What,D1,N1,E1);
  101. DosFSplit(Mask,D2,N2,E2);
  102. {$else}
  103. DosFSplit(Uppercase(What),D1,N1,E1);
  104. DosFSplit(Uppercase(Mask),D2,N2,E2);
  105. {$endif}
  106. MatchesMask:=CmpStr(N2,N1) and CmpStr(E2,E1);
  107. end;
  108. type
  109. PMaskItem=^TMaskItem;
  110. TMaskItem=record
  111. Mask : string[15];
  112. Files : longint;
  113. Size : longint;
  114. Next : PMaskItem;
  115. end;
  116. var
  117. masklist : pmaskitem;
  118. procedure AddMask(s:string);
  119. var
  120. maskitem : PMaskItem;
  121. i : longint;
  122. begin
  123. repeat
  124. i:=pos(' ',s);
  125. if i=0 then
  126. i:=length(s)+1;
  127. New(maskitem);
  128. fillchar(maskitem^,sizeof(tmaskitem),0);
  129. maskitem^.mask:=Copy(s,1,i-1);
  130. maskitem^.next:=masklist;
  131. masklist:=maskitem;
  132. Delete(s,1,i);
  133. until s='';
  134. end;
  135. Var
  136. quiet : boolean = False;
  137. Recurse : Boolean = False;
  138. Verbose : Boolean = False;
  139. NoDelete : Boolean = False;
  140. MaxDepth : Integer = 0;
  141. procedure usage;
  142. begin
  143. Writeln('Delp [options] <directory> [<directory2> [<directory3> ...]');
  144. Writeln('Where options is one of:');
  145. writeln(' -e Delete executables also (Not on Unix)');
  146. writeln(' -x ext Add extension to list of extensions to delete (no dot)');
  147. writeln(' -h Display (this) help message.');
  148. writeln(' -r Recurse into directories.');
  149. writeln(' -n Do not actually delete files.');
  150. writeln(' -m N Maximum depth to recurse into directories (1 based, zero is no max).');
  151. writeln(' -q Quietly performs deleting.');
  152. writeln(' -v Verbose (print names of deleted files).');
  153. Halt(1);
  154. end;
  155. procedure processoptions;
  156. Var c : char;
  157. begin
  158. quiet:=false;
  159. Repeat
  160. C:=Getopt('ehvnqrm:x:');
  161. Case C of
  162. 'e' : AddMAsk('*.exe *.so *.dll');
  163. 'x' : if (optarg<>'') then
  164. AddMask('*.'+optarg);
  165. 'h' : Usage;
  166. 'r' : Recurse:=True;
  167. 'n' : NoDelete:=True;
  168. 'm' : MaxDepth:=StrToInt(optarg);
  169. 'q' : begin
  170. Quiet:=True;
  171. verbose:=False;
  172. end;
  173. 'v' : Verbose:=True;
  174. EndOfOptions : ;
  175. end;
  176. Until C=EndOfOptions;
  177. end;
  178. Procedure DoDir(basedir : string; ALevel : Integer);
  179. var
  180. Dir : TSearchrec;
  181. hp : pmaskitem;
  182. begin
  183. if Verbose and not Quiet then
  184. Writeln('Cleaning directory "',BaseDir,'".');
  185. if FindFirst(basedir+'*.*',faanyfile,Dir)=0 then
  186. begin
  187. repeat
  188. hp:=masklist;
  189. while assigned(hp) do
  190. begin
  191. if ((Dir.Attr and faDirectory)=0) and MatchesMask(Dir.Name,hp^.mask) then
  192. begin
  193. if Verbose then
  194. Writeln('Deleting "',BaseDir+Dir.Name,'"');
  195. if not NoDelete then
  196. DeleteFile(BaseDir+Dir.Name);
  197. inc(hp^.Files);
  198. inc(hp^.Size,Dir.Size);
  199. break;
  200. end;
  201. hp:=hp^.next;
  202. end;
  203. until FindNext(Dir)<>0;
  204. FindClose(Dir);
  205. end;
  206. if Recurse and ((MaxDepth=0) or (ALevel<=MaxDepth)) then
  207. if FindFirst(basedir+allfilesmask,faanyfile,Dir)=0 then
  208. begin
  209. Repeat
  210. if ((Dir.Attr and faDirectory)=faDirectory) and Not ((Dir.Name='.') or (Dir.Name='..')) then
  211. DoDir(IncludeTrailingPathDelimiter(BaseDir+Dir.Name),ALevel+1);
  212. until FindNext(Dir)<>0;
  213. FindClose(Dir);
  214. end;
  215. end;
  216. Procedure PrintResults;
  217. var
  218. Total : longint;
  219. found : boolean;
  220. hp : pmaskitem;
  221. begin
  222. { Write Results }
  223. Total:=0;
  224. found:=false;
  225. hp:=masklist;
  226. while assigned(hp) do
  227. begin
  228. if hp^.Files>0 then
  229. begin
  230. WriteLn(' - Removed ',hp^.Files:2,' ',hp^.Mask,' (',DStr(hp^.Size)+' Bytes)');
  231. inc(Total,hp^.Size);
  232. found:=true;
  233. end;
  234. hp:=hp^.next;
  235. end;
  236. if not found then
  237. WriteLn(' - No Redundant Files Found!')
  238. else
  239. WriteLn(' - Total ',DStr(Total),' Bytes Freed');
  240. end;
  241. var
  242. basedir : string;
  243. i : Integer;
  244. begin
  245. ProcessOptions;
  246. I:=OptInd;
  247. if (OptInd=0) or (OptInd>ParamCount) then
  248. Usage;
  249. { Win32 target }
  250. AddMask('*.ppw *.ow *.aw *.sw');
  251. AddMask('ppas.bat ppas.sh link.res fpcmaked fpcmade fpcmade.* *.fpm');
  252. AddMask('*.tpu *.tpp *.tpw *.tr');
  253. AddMask('*.dcu *.dcp *.bpl');
  254. AddMask('*.log *.bak *.~pas *.~pp *.*~');
  255. AddMask('*.ppu *.o *.a *.s *.or *.compiled');
  256. AddMask('*.pp1 *.o1 *.a1 *.s1');
  257. AddMask('*.ppo *.oo *.ao *.so');
  258. AddMask('*.rst *.rsj');
  259. { OS/2 target }
  260. AddMask('*.oo2 *.so2 *.ppo');
  261. { Amiga target }
  262. AddMask('*.ppa *.asm');
  263. if not quiet then
  264. begin
  265. writeln(Title+' '+Version);
  266. writeln(Copyright);
  267. Writeln;
  268. end;
  269. While (I<=ParamCount) do
  270. begin
  271. BaseDir:=IncludeTrailingPathDelimiter(Paramstr(I));
  272. DoDir(Basedir,1);
  273. Inc(I);
  274. end;
  275. if Not Quiet then
  276. PrintResults;
  277. end.