<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DZone Snippets: decompress code</title>
    <link>http://snippets.dzone.com/posts</link>
    <pubDate>Sun, 27 Jul 2008 03:41:00 GMT</pubDate>
    <description>DZone Snippets: decompress code</description>
    <item>
      <title>Decompress several filetypes with a single script</title>
      <link>http://snippets.dzone.com/posts/show/5785</link>
      <description>// Decompresses Z, gz, bz2, zip, rar, tar, and 7z with a single 'decompress' command&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&lt;br /&gt;#!/bin/bash&lt;br /&gt;&lt;br /&gt;# decompress - will decompress a file, regardless of compression type.&lt;br /&gt;&lt;br /&gt;Z="compress -d"&lt;br /&gt;gz="gunzip"&lt;br /&gt;bz="bunzip2"&lt;br /&gt;zip="unzip -qo"&lt;br /&gt;rar="unrar x -id -y"&lt;br /&gt;tar="tar xf"&lt;br /&gt;7z="p7zip -d"&lt;br /&gt;&lt;br /&gt;if [ $# -eq 0 ]; then&lt;br /&gt;    echo "Usage: decompress file or files to decompress"&gt;&amp;2&lt;br /&gt;    exit 1&lt;br /&gt;fi&lt;br /&gt;&lt;br /&gt;for name&lt;br /&gt;do&lt;br /&gt;	if [ ! -f "$name" ] ; then&lt;br /&gt;		echo "$0: file $name not found. Skipped." &gt;&amp;2&lt;br /&gt;		continue&lt;br /&gt;	fi&lt;br /&gt;&lt;br /&gt;	if [ "$(echo $name | egrep '(\.Z$|\.gz$|\.bz2$|\.zip$|\.rar$|\.tar$|\.tgz$|\.7z$)')" = "" ] ; then&lt;br /&gt;		echo "Skipped file ${name}: it's already decompressed." &lt;br /&gt;      		continue&lt;br /&gt;	fi&lt;br /&gt;&lt;br /&gt;	extension=${name##*.}&lt;br /&gt;&lt;br /&gt;	case "$extension" in&lt;br /&gt;		Z ) echo "Filetype is Z. Decompressing..."&lt;br /&gt;		    $Z "$name"&lt;br /&gt;		    ;;&lt;br /&gt;		gz ) echo "Filetype is gz. Decompressing..."&lt;br /&gt;		     $gz "$name"&lt;br /&gt;		     ;;&lt;br /&gt;		bz2 ) echo "Filetype is bz2. Decompressing..."&lt;br /&gt; 		     $bz "$name"&lt;br /&gt;		     ;;&lt;br /&gt;		zip ) echo "Filetype is zip. Decompressing..."&lt;br /&gt;		      $zip "$name"&lt;br /&gt;		      ;;&lt;br /&gt;		rar ) echo "Filetype is rar. Decompressing..."&lt;br /&gt;		      $rar "$name"&lt;br /&gt;		      ;;&lt;br /&gt;		tar ) echo "Filetype is tar. Decompressing..."&lt;br /&gt;              	      $tar "$name"&lt;br /&gt;              	      ;;&lt;br /&gt;		tgz ) echo "Filetype is tgz. Decompressing..."&lt;br /&gt;              	      $tar "$name"&lt;br /&gt;                     ;;&lt;br /&gt;               7z ) echo "Filetype is 7z. Decompressing..."&lt;br /&gt;                     $7z "$name"&lt;br /&gt;	esac&lt;br /&gt;&lt;br /&gt;done&lt;br /&gt;&lt;br /&gt;exit 0&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;</description>
      <pubDate>Fri, 18 Jul 2008 02:07:02 GMT</pubDate>
      <guid>http://snippets.dzone.com/posts/show/5785</guid>
      <author>zdenton (Zach Denton)</author>
    </item>
    <item>
      <title>Files Joiner/Unjoiner //Pascal class</title>
      <link>http://snippets.dzone.com/posts/show/2197</link>
      <description>This is just a snippet since I didn't added some units that can be replaced without major efforts:&lt;br /&gt;- PathParser.pas: parses paths shortcuts (it's on my bigbold snippets, search on my tags)&lt;br /&gt;- Stack.pas: implements a simple stack (it's on my bigbold snippets, search on my tags)&lt;br /&gt;- ZlibEx.pas: used to compress/decompress the file contents (My ZlibEx is a modified version of this file: http://www.dellapasqua.com/delphizlib)&lt;br /&gt;- MD5.pas: used to calculate the file hash and check consistency when unjoining files&lt;br /&gt;- SysUtils2: Some idiot functions =b&lt;br /&gt;&lt;br /&gt;I used this in a personalized installer that I've made in my first job =b&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&lt;br /&gt;unit FileJoiner;&lt;br /&gt;&lt;br /&gt;interface&lt;br /&gt;&lt;br /&gt;uses&lt;br /&gt;  SysUtils, SysUtils2, Classes, MD5, ZlibEx, PathParser, Stack;&lt;br /&gt;&lt;br /&gt;type&lt;br /&gt;  TOverwriteMode = ( omNo, omAskUser, omIfNewer, omIfOlder, omIfDiff );&lt;br /&gt;  TOverwriteAction = ( oaOverwriteAll, oaNoOverwriteAll, oaYes, oaNo );&lt;br /&gt;&lt;br /&gt;  TFileHeader = record&lt;br /&gt;    MD5Hash: TDigestStr;&lt;br /&gt;    ModificationDate: TDateTime;&lt;br /&gt;    Attributes: LongWord;&lt;br /&gt;    Overwrite: TOverwriteMode;&lt;br /&gt;    Size: Int64;&lt;br /&gt;    MustKeep: Boolean;&lt;br /&gt;  end;&lt;br /&gt;&lt;br /&gt;  TFileJoinerItem = class&lt;br /&gt;  public&lt;br /&gt;    Source, Destiny: string;&lt;br /&gt;    MustKeep, Recurse: Boolean;&lt;br /&gt;    Overwrite: TOverwriteMode;&lt;br /&gt;&lt;br /&gt;    constructor Create( const FromPath, ToPath: string; const OverwriteMode: TOverwriteMode = omIfNewer; const Recursive: Boolean = True; const MustKeepFile: Boolean = False ); overload;&lt;br /&gt;    function Assign( Item: TFileJoinerItem ): TFileJoinerItem;&lt;br /&gt;&lt;br /&gt;    procedure Save( const Stream: TStream );&lt;br /&gt;    procedure Load( const Stream: TStream );&lt;br /&gt;  end;&lt;br /&gt;&lt;br /&gt;  TCustomFileJoiner = class;&lt;br /&gt;&lt;br /&gt;  TFileJoinerFilesCallback = procedure( Sender: TCustomFileJoiner; Item: TFileJoinerItem ) of object;&lt;br /&gt;  TFileJoinerNotifyEvent = procedure( Sender: TCustomFileJoiner ) of object;&lt;br /&gt;  TFileJoinerFileExists = procedure( Sender: TCustomFileJoiner; var CanOverwrite: TOverwriteAction ) of object;&lt;br /&gt;&lt;br /&gt;  TJoinerStatus = ( jsIdle, jsJoining, jsUnjoining );&lt;br /&gt;&lt;br /&gt;  TCustomFileJoiner = class&lt;br /&gt;  private&lt;br /&gt;    FStream: TStream;&lt;br /&gt;    FCurFile, FTotalFiles: LongWord;&lt;br /&gt;    FCurSize, FTotalSize, FCurPosition, FCurWrittenBytes: Int64;&lt;br /&gt;    FCurFilename: string;&lt;br /&gt;    FCurFileInfo: TFileHeader;&lt;br /&gt;    FOnFileExists: TFileJoinerFileExists;&lt;br /&gt;    FOnWorkEnd, FOnWorkBegin, FOnWork, FOnProcessFile: TFileJoinerNotifyEvent;&lt;br /&gt;&lt;br /&gt;    procedure ProgressNotifier( Sender: TObject );&lt;br /&gt;&lt;br /&gt;  public&lt;br /&gt;    //properties&lt;br /&gt;    property CurFilename: string read FCurFilename;&lt;br /&gt;    property CurFileInfo: TFileHeader read FCurFileInfo;&lt;br /&gt;    property CurFilePosition: Int64 read FCurPosition;&lt;br /&gt;    property CurWrittenBytes: Int64 read FCurWrittenBytes;&lt;br /&gt;    property CurSize: Int64 read FCurSize;&lt;br /&gt;    property CurFile: LongWord read FCurFile;&lt;br /&gt;&lt;br /&gt;    property TotalSize: Int64 read FTotalSize;&lt;br /&gt;    property TotalFiles: LongWord read FTotalFiles;&lt;br /&gt;&lt;br /&gt;    //events&lt;br /&gt;    property OnWorkBegin: TFileJoinerNotifyEvent read FOnWorkBegin write FOnWorkBegin;&lt;br /&gt;    property OnWork: TFileJoinerNotifyEvent read FOnWork write FOnWork;&lt;br /&gt;    property OnWorkEnd: TFileJoinerNotifyEvent read FOnWorkEnd write FOnWorkEnd;&lt;br /&gt;    property OnProcessFile: TFileJoinerNotifyEvent read FOnProcessFile write FOnProcessFile;&lt;br /&gt;    property OnFileExists: TFileJoinerFileExists read FOnFileExists write FOnFileExists;&lt;br /&gt;  end;&lt;br /&gt;&lt;br /&gt;  TFileJoiner = class( TCustomFileJoiner )&lt;br /&gt;  private&lt;br /&gt;    FPaths: TList;&lt;br /&gt;&lt;br /&gt;    function GetItem(const Index: Integer): TFileJoinerItem;&lt;br /&gt;    function GetCount: Integer;&lt;br /&gt;    procedure StreamFile( Sender: TCustomFileJoiner; Item: TFileJoinerItem );&lt;br /&gt;    procedure Compress( Input: TStream );&lt;br /&gt;&lt;br /&gt;  public&lt;br /&gt;    constructor Create;&lt;br /&gt;    destructor Destroy; override;&lt;br /&gt;&lt;br /&gt;    procedure Join( const Filename: string ); overload;&lt;br /&gt;    procedure Join( const Stream: TStream ); overload;&lt;br /&gt;&lt;br /&gt;    procedure SaveList( const Filename: string ); overload;&lt;br /&gt;    procedure SaveList( Stream: TStream ); overload;&lt;br /&gt;    procedure LoadList( const Filename: string ); overload;&lt;br /&gt;    procedure LoadList( Stream: TStream ); overload;&lt;br /&gt;&lt;br /&gt;    procedure CountFiles;&lt;br /&gt;&lt;br /&gt;    function Add( const FromPath, ToPath: string; const OverwriteMode: TOverwriteMode = omIfNewer; const Recursive: Boolean = False; const MustKeep: Boolean = False ): Integer;&lt;br /&gt;    procedure Clear;&lt;br /&gt;    procedure Remove( const Index: Integer );&lt;br /&gt;    procedure ListFiles( const Callback: TFileJoinerFilesCallback );&lt;br /&gt;&lt;br /&gt;    property Count: Integer read GetCount;&lt;br /&gt;    property Items[ const Index: Integer ]: TFileJoinerItem read GetItem; default;&lt;br /&gt;  end;&lt;br /&gt;&lt;br /&gt;  TFileUnjoiner = class( TCustomFileJoiner )&lt;br /&gt;  private&lt;br /&gt;    FDataBegin: Int64;&lt;br /&gt;    procedure Decompress( Output: TStream );&lt;br /&gt;&lt;br /&gt;  public&lt;br /&gt;    procedure Assign( const Filename: string ); overload;&lt;br /&gt;    procedure Assign( Stream: TStream ); overload;&lt;br /&gt;    procedure UnJoin;&lt;br /&gt;  end;&lt;br /&gt;&lt;br /&gt;implementation&lt;br /&gt;&lt;br /&gt;{ TCustomFileJoiner }&lt;br /&gt;&lt;br /&gt;procedure TCustomFileJoiner.ProgressNotifier(Sender: TObject);&lt;br /&gt;begin&lt;br /&gt;  if Assigned( FOnWork ) then&lt;br /&gt;    with TStream( Sender ) do&lt;br /&gt;    begin&lt;br /&gt;      FCurWrittenBytes := Position - FCurPosition;&lt;br /&gt;      FCurPosition := Position;&lt;br /&gt;      FOnWork( Self );&lt;br /&gt;    end;&lt;br /&gt;end;&lt;br /&gt;&lt;br /&gt;{ TFileJoiner }&lt;br /&gt;&lt;br /&gt;procedure TFileJoiner.Join( const Filename: string );&lt;br /&gt;begin&lt;br /&gt;  FStream := TFileStream.Create( Filename, fmCreate );&lt;br /&gt;  try&lt;br /&gt;    Join( FStream );&lt;br /&gt;  finally&lt;br /&gt;    FStream.Free;&lt;br /&gt;  end;&lt;br /&gt;end;&lt;br /&gt;&lt;br /&gt;procedure TFileJoiner.Join( const Stream: TStream );&lt;br /&gt;var&lt;br /&gt;  Pos: array[0..1] of Int64;&lt;br /&gt;begin&lt;br /&gt;  FStream := Stream;&lt;br /&gt;  if Assigned( FOnWorkBegin ) then&lt;br /&gt;    FOnWorkBegin( Self );&lt;br /&gt;&lt;br /&gt;  FCurFile := 0;&lt;br /&gt;  FCurSize := 0;&lt;br /&gt;&lt;br /&gt;  //record position to get back later and reserve space on the file to record the "totals"&lt;br /&gt;  Pos[0] := FStream.Position;&lt;br /&gt;  FStream.Seek( SizeOf( FCurFile ) + SizeOf( FCurSize ), soCurrent );&lt;br /&gt;&lt;br /&gt;  //write files&lt;br /&gt;  ListFiles( StreamFile );&lt;br /&gt;&lt;br /&gt;  //write the totals and get back&lt;br /&gt;  Pos[1] := Stream.Position;&lt;br /&gt;  FStream.Position := Pos[0];&lt;br /&gt;  FStream.Write( FCurFile, SizeOf( FCurFile ) );&lt;br /&gt;  FStream.Write( FCurSize, SizeOf( FCurSize ) );&lt;br /&gt;  FStream.Position := Pos[1];&lt;br /&gt;&lt;br /&gt;  //job done&lt;br /&gt;  if Assigned( FOnWorkEnd ) then&lt;br /&gt;    FOnWorkEnd( Self );&lt;br /&gt;end;&lt;br /&gt;&lt;br /&gt;procedure TFileJoiner.StreamFile( Sender: TCustomFileJoiner; Item: TFileJoinerItem );&lt;br /&gt;var&lt;br /&gt;  InputFile: TFileStream;&lt;br /&gt;  Pos: array[0..1] of Int64;&lt;br /&gt;begin&lt;br /&gt;  try&lt;br /&gt;    Inc( FCurFile );&lt;br /&gt;    FCurPosition := 0;&lt;br /&gt;    FCurFilename := Item.Source;&lt;br /&gt;&lt;br /&gt;    FCurFileInfo.MD5Hash := FileMD5Digest( Item.Source );&lt;br /&gt;    FCurFileInfo.ModificationDate := FileDateToDateTime( FileAge( Item.Source ) );&lt;br /&gt;    FCurFileInfo.Attributes := FileGetAttr( Item.Source );&lt;br /&gt;    FCurFileInfo.Overwrite := Item.Overwrite;&lt;br /&gt;&lt;br /&gt;    InputFile := TFileStream.Create( Item.Source, fmOpenRead or fmShareDenyWrite );&lt;br /&gt;    try&lt;br /&gt;      FCurFileInfo.Size := InputFile.Size;&lt;br /&gt;      if Assigned( FOnProcessFile ) then&lt;br /&gt;        FOnProcessFile( Self );&lt;br /&gt;&lt;br /&gt;      Pos[0] := FStream.Position;&lt;br /&gt;      //reserve space for the file header and EOF position&lt;br /&gt;      FStream.Seek( SizeOf( FCurFileInfo ) + SizeOf( Pos[0] ), soCurrent );&lt;br /&gt;      StringWrite( FStream, Item.Destiny );&lt;br /&gt;&lt;br /&gt;      Compress( InputFile );&lt;br /&gt;&lt;br /&gt;      //update the header and get back&lt;br /&gt;      Pos[1] := FStream.Position;&lt;br /&gt;      FStream.Position := Pos[0];&lt;br /&gt;      FStream.Write( FCurFileInfo, SizeOf( FCurFileInfo ) );&lt;br /&gt;      FStream.Write( Pos[1], SizeOf( Pos[1] ) );&lt;br /&gt;      FStream.Position := Pos[1];&lt;br /&gt;&lt;br /&gt;      //update summary&lt;br /&gt;      Inc( FCurSize, FCurFileInfo.Size );&lt;br /&gt;    finally&lt;br /&gt;      InputFile.Free;&lt;br /&gt;    end;&lt;br /&gt;  except&lt;br /&gt;    on E: Exception do&lt;br /&gt;      raise EWriteError.CreateFmt( '%s.StreamFile: Error on joining: "%s" - %s',  [ ClassName, FCurFilename, E.Message ] );&lt;br /&gt;  end;&lt;br /&gt;end;&lt;br /&gt;&lt;br /&gt;function TFileJoiner.Add(const FromPath, ToPath: string;&lt;br /&gt;  const OverwriteMode: TOverwriteMode; const Recursive: Boolean; const MustKeep: Boolean ): Integer;&lt;br /&gt;begin&lt;br /&gt;  Result := FPaths.Add( TFileJoinerItem.Create( FromPath, ToPath, OverwriteMode, Recursive, MustKeep ) );&lt;br /&gt;end;&lt;br /&gt;&lt;br /&gt;procedure TFileJoiner.Clear;&lt;br /&gt;var&lt;br /&gt;  I: Integer;&lt;br /&gt;begin&lt;br /&gt;  for I := FPaths.Count - 1 downto 0 do&lt;br /&gt;  begin&lt;br /&gt;    TFileJoinerItem( FPaths[I] ).Free;&lt;br /&gt;    FPaths.Delete( I );&lt;br /&gt;  end;&lt;br /&gt;end;&lt;br /&gt;&lt;br /&gt;constructor TFileJoiner.Create;&lt;br /&gt;begin&lt;br /&gt;  FPaths := TList.Create;&lt;br /&gt;end;&lt;br /&gt;&lt;br /&gt;destructor TFileJoiner.Destroy;&lt;br /&gt;begin&lt;br /&gt;  Clear;&lt;br /&gt;  FPaths.Free;&lt;br /&gt;  inherited;&lt;br /&gt;end;&lt;br /&gt;&lt;br /&gt;procedure TFileJoiner.CountFiles;&lt;br /&gt;type&lt;br /&gt;  PStackItem = ^TStackItem;&lt;br /&gt;  TStackItem = record&lt;br /&gt;    Data: PChar;&lt;br /&gt;    Searcher: TSearchRec;&lt;br /&gt;  end;&lt;br /&gt;&lt;br /&gt;var&lt;br /&gt;  I: Integer;&lt;br /&gt;  Path, Filter: string;&lt;br /&gt;  Stack: TStack;&lt;br /&gt;  CurStack, X: PStackItem;&lt;br /&gt;begin&lt;br /&gt;  FTotalFiles := 0;&lt;br /&gt;  FTotalSize := 0;&lt;br /&gt;&lt;br /&gt;  Stack := TStack.Create;&lt;br /&gt;  try&lt;br /&gt;    for I := 0 to FPaths.Count - 1 do&lt;br /&gt;    begin&lt;br /&gt;      Path := Self[I].Source;&lt;br /&gt;      if LastDelimiter( '*?', ExtractFileName( Path ) ) &lt;&gt; 0 then&lt;br /&gt;      begin&lt;br /&gt;        Filter := ExtractFileName( Path );&lt;br /&gt;        Path := ExtractFilePath( Path );&lt;br /&gt;      end&lt;br /&gt;      else if FileExists( Path ) then&lt;br /&gt;      else if DirectoryExists( Path ) then&lt;br /&gt;      begin&lt;br /&gt;        Filter := '*';&lt;br /&gt;        Path := AddSlash( Path );&lt;br /&gt;      end&lt;br /&gt;      else&lt;br /&gt;        raise Exception.CreateFmt( '%s.GetFilesSumary: "%s" n&#227;o encontrado', [ ClassName, Path ] );&lt;br /&gt;&lt;br /&gt;      New( CurStack );&lt;br /&gt;      CurStack^.Data := CopyString( Path );&lt;br /&gt;      repeat&lt;br /&gt;        with CurStack^ do&lt;br /&gt;        begin&lt;br /&gt;          if FindFirst( Data + Filter, faDirectory, Searcher ) = 0 then&lt;br /&gt;          begin&lt;br /&gt;            repeat&lt;br /&gt;              Inc( FTotalFiles );&lt;br /&gt;              Inc( FTotalSize, Searcher.Size );&lt;br /&gt;            until FindNext( Searcher ) &lt;&gt; 0;&lt;br /&gt;            FindClose( Searcher );&lt;br /&gt;          end;&lt;br /&gt;&lt;br /&gt;          if Self[I].Recurse and ( FindFirst( Data + Filter, faArchive, Searcher ) = 0 ) then&lt;br /&gt;          begin&lt;br /&gt;            repeat&lt;br /&gt;              if Searcher.Name[1] &lt;&gt; '.' then&lt;br /&gt;              begin&lt;br /&gt;                New( X );&lt;br /&gt;                X^.Data := CopyString( AddSlash( Data + Searcher.Name ) );&lt;br /&gt;                Stack.Push( X );&lt;br /&gt;              end;&lt;br /&gt;            until FindNext( Searcher ) &lt;&gt; 0;&lt;br /&gt;            FindClose( Searcher );&lt;br /&gt;          end;&lt;br /&gt;          FreeMem( Data );&lt;br /&gt;          Dispose( CurStack );&lt;br /&gt;          CurStack := Stack.Pop;&lt;br /&gt;        end;&lt;br /&gt;      until CurStack = nil;&lt;br /&gt;    end;&lt;br /&gt;  finally&lt;br /&gt;    Stack.Free;&lt;br /&gt;  end;&lt;br /&gt;end;&lt;br /&gt;&lt;br /&gt;function TFileJoiner.GetItem(const Index: Integer): TFileJoinerItem;&lt;br /&gt;begin&lt;br /&gt;  Result := FPaths.Items[ Index ];&lt;br /&gt;end;&lt;br /&gt;&lt;br /&gt;function TFileJoiner.GetCount: Integer;&lt;br /&gt;begin&lt;br /&gt;  Result := FPaths.Count;&lt;br /&gt;end;&lt;br /&gt;&lt;br /&gt;procedure TFileJoiner.ListFiles( const Callback: TFileJoinerFilesCallback);&lt;br /&gt;type&lt;br /&gt;  PStackItem = ^TStackItem;&lt;br /&gt;  TStackItem = record&lt;br /&gt;    Source, Destiny: PChar;&lt;br /&gt;    Searcher: TSearchRec;&lt;br /&gt;  end;&lt;br /&gt;&lt;br /&gt;var&lt;br /&gt;  Stack: TStack;&lt;br /&gt;  Filter: string;&lt;br /&gt;  Current, X: PStackItem;&lt;br /&gt;  Data: TFileJoinerItem;&lt;br /&gt;  I: Integer;&lt;br /&gt;begin&lt;br /&gt;  Stack := TStack.Create;&lt;br /&gt;  try&lt;br /&gt;    Data := TFileJoinerItem.Create;&lt;br /&gt;    try&lt;br /&gt;      for I := 0 to FPaths.Count - 1 do&lt;br /&gt;      begin&lt;br /&gt;        Data.Assign( Self[I] );&lt;br /&gt;        with Data do&lt;br /&gt;        begin&lt;br /&gt;          Destiny := AddSlash( Destiny );&lt;br /&gt;          if LastDelimiter( '*?', ExtractFileName( Source ) ) &lt;&gt; 0 then&lt;br /&gt;          begin&lt;br /&gt;            Filter := ExtractFileName( Source );&lt;br /&gt;            Source := ExtractFilePath( Source );&lt;br /&gt;          end&lt;br /&gt;          else if FileExists( Source ) then&lt;br /&gt;          begin&lt;br /&gt;            Destiny := Destiny + ExtractFileName( Data.Source );&lt;br /&gt;            Callback( Self, Data );&lt;br /&gt;            Continue;&lt;br /&gt;          end&lt;br /&gt;          else if DirectoryExists( Source ) then&lt;br /&gt;          begin&lt;br /&gt;            Filter := '*';&lt;br /&gt;            Destiny := AddSlash( Destiny + ExtractFileName( RemoveSlash( Source ) ) );&lt;br /&gt;            Source := AddSlash( Source );&lt;br /&gt;          end&lt;br /&gt;          else&lt;br /&gt;            raise Exception.CreateFmt( '%s.ListFiles: "%s" n&#227;o encontrado', [ ClassName, Source ] );&lt;br /&gt;        end;&lt;br /&gt;&lt;br /&gt;        New( Current );&lt;br /&gt;        with Current^ do&lt;br /&gt;        begin&lt;br /&gt;          Source := CopyString( Data.Source );&lt;br /&gt;          Destiny := CopyString( Data.Destiny );&lt;br /&gt;        end;&lt;br /&gt;&lt;br /&gt;        repeat&lt;br /&gt;          with Current^ do&lt;br /&gt;          begin&lt;br /&gt;            if FindFirst( Source + Filter, faDirectory, Searcher ) = 0 then&lt;br /&gt;            begin&lt;br /&gt;              repeat&lt;br /&gt;                Data.Source := Source + Searcher.Name;&lt;br /&gt;                Data.Destiny := Destiny + Searcher.Name;&lt;br /&gt;                Callback( Self, Data )&lt;br /&gt;              until FindNext( Searcher ) &lt;&gt; 0;&lt;br /&gt;              FindClose( Searcher );&lt;br /&gt;            end;&lt;br /&gt;&lt;br /&gt;            if Data.Recurse and ( FindFirst( Source + '*', faArchive, Searcher ) = 0 ) then&lt;br /&gt;            begin&lt;br /&gt;              repeat&lt;br /&gt;                if Searcher.Name[1] &lt;&gt; '.' then&lt;br /&gt;                begin&lt;br /&gt;                  New( X );&lt;br /&gt;                  X^.Source := CopyString( AddSlash( Source + Searcher.Name ) );&lt;br /&gt;                  X^.Destiny := CopyString( AddSlash( Destiny + Searcher.Name ) );&lt;br /&gt;                  Stack.Push( X );&lt;br /&gt;                end;&lt;br /&gt;              un</description>
      <pubDate>Thu, 15 Jun 2006 19:09:02 GMT</pubDate>
      <guid>http://snippets.dzone.com/posts/show/2197</guid>
      <author>jonasraoni (Jonas Raoni Soares Silva)</author>
    </item>
  </channel>
</rss>
