Archivo

Archive for 27 marzo 2009

Eliminación de directorios con C++

27 marzo, 2009 6 comentarios

En esta ocasión presento algo que parece bastante sencillo, pero que cuesta implementar, especialmente si se utiliza el compiladorcito de Borland. Se trata de un programa que elimina directorios completos.

El desafío lo presentan las restricciones del lenguaje y del compilador. Sólo se puede eliminar un directorio una vez que no contenga archivos ni subdirectorios, y que no se encuentre en uso por algún proceso. En pocas palabras, no existe alguna función que reciba el nombre del directorio y lo elimine. Bueno, este procedimiento lo hace.

Aquí está el código, bien comentado espero:

#include <direct>
#include <dirent>
#include <stdio>
#include <string>

void eliminarDirectorio(char *directorio);

void main()
{
    char *directorio;
    // Ojo, un char* sin diagonal inversa al final. Pero podría
    // ser prácticamente cualquier directorio (así que cuidado).
    // También debe ser el nombre completo, incluyendo la letra
    // de la unidad de disco.

    directorio = "C:\\New Folder";
    eliminarDirectorio(directorio);
}

void eliminarDirectorio(char *directorio)
{
    // Se utiliza para listar un directorio.
    DIR *folder;
    // En Borland, la estructura dirent únicamente tiene el
    // campo d_name, que es el nombre del archivo o
    // subdirectorio. Muy lamentable y una limitante
    // considerable.

    struct dirent *entry;
    // Contendrá el nombre del archivo o subdirectorio contenido
    // en el directorio que se quiere eliminar.

    string nombre;
    // Hay que "moverse" hacia dentro del subdirectorio, porque
    // como sólo se dispone del nombre del archivo o
    // subdirectorio, no puede "haber" nombres de directorios en
    // la ruta de lo que se quiere eliminar. Hay que estar en el
    // mismo directorio.

    chdir(directorio);
    // Se abre el directorio para poder recorrer los elementos
    // que contiene.

    folder = opendir(directorio);
    // Esto recorre todos los subdirectorios y archivos dentro
    // del directorio "original".

    while (entry = readdir(folder))
        // Otra vez, por la estructura dirent de Borland, no se
        // puede usar el campo d_type. Esto excluye al
        // directorio actual y al directorio que lo contiene de
        // la lista de lo que se va a eliminar.

        if (strcmp(entry->d_name, ".") != 0 &&
            strcmp(entry->d_name, "..") != 0)
        {
            // Al fin, el nombre del archivo o subdirectorio.
            nombre = entry->d_name;
            // La función remove sólo funciona con archivos. Si
            // no tiene éxito, es porque lo que trató de
            // eliminar fue un directorio. Entonces retorna 1,
            // indicando que la operación falló. Y significa que
            // se trató de un subdirectorio, posiblemente con
            // más archivos y subdirectorios.

            if (remove(nombre.c_str()))
            {
                // Considero que 600 caracteres son más que
                // suficiente para una ruta. Igual puede
                // aumentarse.

                char dir[600];
                // Concatena al nombre del directorio que se
                // quiere eliminar, una diagonal inversa y el
                // nombre del subdirectorio.

                sprintf(dir, "%s\\%s", directorio,
                        entry->d_name);
                // Y tenía que serlo, un procedimiento
                // recursivo. Se llama a sí mismo, pero con el
                // nombre del subdirectorio esta vez.

                eliminarDirectorio(dir);
            }
        }
    // Cierra el directorio que se recorrió. De no hacerlo la
    // eliminación del directorio no es posible.

    closedir(folder);
    // Se mueve al directorio superior, otro requisito para la
    // eliminación.

    chdir("..");
    // Elimina el directorio recorrido (posiblemente el
    // subdirectorio de una de las llamadas recursivas).

    _rmdir(directorio);
}

En cuanto al funcionamiento, el código lo explica bien, pero por si acaso:

  1. Se abre el directorio que se quiere eliminar.
  2. Se recorren los contenidos del directorio. Si son archivos se eliminan. Si es un subdirectorio, el procedimiento se llama a sí mismo, pero para eliminar el subdirectorio.
  3. La ruta de funcionamiento del programa se mueve al directorio superior.
  4. Se elimina el directorio con el que se llamó al procedimiento.

Lo bonito de este programa es que funciona con el compilador Borland 5.02, por lo menos.

Categorías:Programación