19 junio 2007

Recorrer un árbol de directorios

El procedimiento que voy a mostrar a continuación recorre el contenido de directorios, subdirectorios y archivos volcando la información en un campo memo (TMemo).

Modificando su comportamiento puede ser utilizado para realizar copias de seguridad, calcular el tamaño de un directorio o borrar el contenido de los mismos.

El procedimiento RecorrerDirectorio toma como primer parámetro la ruta que desea recorrer y como segundo parámetro si deseamos que busque también en subdirectorios:

procedure TFBuscar.RecorrerDirectorio( sRuta: String; bIncluirSubdirectorios: Boolean );
var
Directorio: TSearchRec;
iResultado: Integer;
begin
// Si la ruta no termina en contrabarra se la ponemos
if sRuta[Length(sRuta)] <> '\' then
sRuta := sRuta + '\';

// ¿No existe el directorio que vamos a recorrer?
if not DirectoryExists( sRuta ) then
begin
Application.MessageBox( PChar( 'No existe el directorio:' + #13 + #13 + sRuta ), 'Error', MB_ICONSTOP );
Exit;
end;

iResultado := FindFirst( sRuta + '*.*', FaAnyfile, Directorio );
while iResultado = 0 do
begin
// ¿Es un directorio y hay que entrar en él?
if ( Directorio.Attr and faDirectory = faDirectory ) and bIncluirSubdirectorios then
begin
if ( Directorio.Name <> '.' ) and ( Directorio.Name <> '..' ) then
RecorrerDirectorio( sRuta + Directorio.Name, True );
end
else
// ¿No es el nombre de una unidad ni un directorio?
if ( Directorio.Attr and faVolumeId <> faVolumeID ) then
Archivos.Lines.Add( sRuta + Directorio.Name );

iResultado := FindNext( Directorio );
end;

SysUtils.FindClose( Directorio );
end;

Antes de comenzar a buscar directorios se asegura de que la ruta que le pasemos termine en contrabarra y en el caso de que no sea así se la pone al final.

Para recorrer un directorio utiliza la estructura de datos TSearchRec la cual se utiliza para depositar en ella la información del contenido de un directorio mediante las funciones FindFirst y FindNext.

TSearchRec no contiene la información de todo el directorio sino que es un puntero al directorio o archivo actual. Sólo mirando los atributos mediante la propiedad Attr podemos saber si lo que estamos leyendo es un directorio, archivo o unidad.

También se cuida de saltarse los directorios '.' y '..' ya que sino el procedimiento recursivo RecorrerDirectorio se volvería loco hasta reventar la pila.

Realizar modificaciones para cambiar su comportamiento puede ser peligroso si no lleváis cuidado ya que la recursividad puede de dejar sin memoria la aplicación. Al realizar tareas como borrar subdirectorios mucho cuidado no darle la ruta C:\. Mejor hacer ensayos volcando el contenido en un Memo hasta tener el resultado deseado.

Pruebas realizadas en Delphi 7.

Publicidad