2009-04-09 13 views
26

¿Cómo puedo eliminar una carpeta usando C++?¿Cómo eliminar una carpeta en C++?

Si no existe una forma multiplataforma, ¿cómo hacerlo para los sistemas operativos más populares: Windows, Linux, Mac, iOS, Android? ¿Funcionaría una solución POSIX para todos?

Respuesta

0

El estándar C++ define la función remove(), que puede o no eliminar una carpeta, dependiendo de la implementación. Si no es así, debe usar una función específica de implementación como rmdir().

4

El directorio debe estar vacío y el programa debe tener permisos para eliminar lo

pero la función llamada rmdir lo hará

rmdir("C:/Documents and Settings/user/Desktop/itsme") 
+4

¿Qué archivo de encabezado usa en Windows? –

+0

use _rmdir para Windows, y el encabezado es '#include ' Creo, igual que _mkdir – Mich

8

El directorio debe estar vacío.

BOOL RemoveDirectory(LPCTSTR lpPathName); 
+12

Esto es solo Windows, creo? Me parece gracioso que Vinay tenga un avatar de Apple, pero publica una respuesta específica de Windows. ;) – Aardvark

+9

Vinay ya no tiene avatar de Apple;) – sergtk

+3

Vinay tiene un avatar de Android ahora :) –

-2

Si está utilizando Windows, a continuación, echar un vistazo a this link. De lo contrario, puede buscar su api de versión específica del sistema operativo. No creo que C++ tenga una forma de plataforma cruzada para hacerlo. Al final, NO es el trabajo de C++, es el trabajo del sistema operativo.

16

eliminar la carpeta (sub_folders y archivos) en Windows (VisualC++) no utilizar las API de Shell, esta es la mejor muestra de trabajo:

#include <string> 
#include <iostream> 

#include <windows.h> 
#include <conio.h> 


int DeleteDirectory(const std::string &refcstrRootDirectory, 
        bool    bDeleteSubdirectories = true) 
{ 
    bool   bSubdirectory = false;  // Flag, indicating whether 
               // subdirectories have been found 
    HANDLE   hFile;      // Handle to directory 
    std::string  strFilePath;     // Filepath 
    std::string  strPattern;     // Pattern 
    WIN32_FIND_DATA FileInformation;    // File information 


    strPattern = refcstrRootDirectory + "\\*.*"; 
    hFile = ::FindFirstFile(strPattern.c_str(), &FileInformation); 
    if(hFile != INVALID_HANDLE_VALUE) 
    { 
    do 
    { 
     if(FileInformation.cFileName[0] != '.') 
     { 
     strFilePath.erase(); 
     strFilePath = refcstrRootDirectory + "\\" + FileInformation.cFileName; 

     if(FileInformation.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) 
     { 
      if(bDeleteSubdirectories) 
      { 
      // Delete subdirectory 
      int iRC = DeleteDirectory(strFilePath, bDeleteSubdirectories); 
      if(iRC) 
       return iRC; 
      } 
      else 
      bSubdirectory = true; 
     } 
     else 
     { 
      // Set file attributes 
      if(::SetFileAttributes(strFilePath.c_str(), 
           FILE_ATTRIBUTE_NORMAL) == FALSE) 
      return ::GetLastError(); 

      // Delete file 
      if(::DeleteFile(strFilePath.c_str()) == FALSE) 
      return ::GetLastError(); 
     } 
     } 
    } while(::FindNextFile(hFile, &FileInformation) == TRUE); 

    // Close handle 
    ::FindClose(hFile); 

    DWORD dwError = ::GetLastError(); 
    if(dwError != ERROR_NO_MORE_FILES) 
     return dwError; 
    else 
    { 
     if(!bSubdirectory) 
     { 
     // Set directory attributes 
     if(::SetFileAttributes(refcstrRootDirectory.c_str(), 
           FILE_ATTRIBUTE_NORMAL) == FALSE) 
      return ::GetLastError(); 

     // Delete directory 
     if(::RemoveDirectory(refcstrRootDirectory.c_str()) == FALSE) 
      return ::GetLastError(); 
     } 
    } 
    } 

    return 0; 
} 


int main() 
{ 
    int   iRC     = 0; 
    std::string strDirectoryToDelete = "c:\\mydir"; 


    // Delete 'c:\mydir' without deleting the subdirectories 
    iRC = DeleteDirectory(strDirectoryToDelete, false); 
    if(iRC) 
    { 
    std::cout << "Error " << iRC << std::endl; 
    return -1; 
    } 

    // Delete 'c:\mydir' and its subdirectories 
    iRC = DeleteDirectory(strDirectoryToDelete); 
    if(iRC) 
    { 
    std::cout << "Error " << iRC << std::endl; 
    return -1; 
    } 

    // Wait for keystroke 
    _getch(); 

    return 0; 
} 

Fuente: http://www.codeguru.com/forum/showthread.php?t=239271

+4

Gracias por publicar algo que no fue Boost o una llamada al sistema(). –

+0

Pero un día el enlace estará muerto. ¿Vas a incluir el código relevante en la respuesta? – jogojapan

+0

Parece que esta solución puede fallar debido a las razas del sistema de archivos: DeleteFile no es atómico, lo que significa que la eliminación del directorio que lo contiene puede fallar porque el directorio aún no está vacío. Esta charla explica el problema en detalle y brinda una manera más segura de eliminar un directorio/árbol en Windows: https://www.youtube.com/watch?v=uhRWMGBjlO8 –

0

// para Windows:

#include <direct.h> 


if(_rmdir("FILEPATHHERE") != -1) 
{ 
    //success  
} else { 
    //failure 
} 
+2

Esto no funciona para rutas Unicode. No es útil en la mayoría de las aplicaciones modernas. – strcat

5

Uso SHFileOperation para eliminar la carpeta recursivelly

2

También puede probar esto si estás en Linux:

system("rm -r path"); 
+1

El mejor enfoque para Android, thx. –

0

Try sistema de uso "rmdir -s -q file_to_delte" .
Esto eliminará la carpeta y todos los archivos en ella.

+1

En POSIX, no: no hay ninguna bandera '-s' allí. En Windows, esto intenta eliminar los directorios '-s' y' -q'. – MSalters

3
void remove_dir(char *path) 
{ 
     struct dirent *entry = NULL; 
     DIR *dir = NULL; 
     dir = opendir(path); 
     while(entry = readdir(dir)) 
     { 
       DIR *sub_dir = NULL; 
       FILE *file = NULL; 
       char abs_path[100] = {0}; 
       if(*(entry->d_name) != '.') 
       { 
         sprintf(abs_path, "%s/%s", path, entry->d_name); 
         if(sub_dir = opendir(abs_path)) 
         { 
           closedir(sub_dir); 
           remove_dir(abs_path); 
         } 
         else 
         { 
           if(file = fopen(abs_path, "r")) 
           { 
             fclose(file); 
             remove(abs_path); 
           } 
         } 
       } 
     } 
     remove(path); 
} 
+0

si 'ruta' termina con un '/' entonces solo el/contenido/debe ser eliminado y el directorio - ahora vacío - debe permanecer; también 'if (* (entry-> d_name)! = '.')' debería buscar "." y "..", de la forma en que actualmente no eliminará los archivos ocultos. de lo contrario, esto es genial. – slashmais

0

Mi propia implementación basa fuera HB0 que también le permite ver el número de archivos en cada carpeta también con un poco de aumento de rendimiento.

#include <string> 
#include <iostream> 
#include <cstdlib> 
#include <cstdio> 
#include <windows.h> 
#include <conio.h> 

union seperated { 
    struct { 
    unsigned int low; 
    unsigned int high; 
    } uint; 
    unsigned long long ull; 
}; 

unsigned long long num_dirs = 1; 
unsigned long long num_files = 0; 
seperated size_files; 

int DeleteDirectory(char* refRootDirectory);  //predeclare it 

int DeleteDirectory(char* refRootDirectory) { 
    HANDLE  hFile;    // Handle to directory 
    std::string strFilePath;   // Filepath 
    WIN32_FIND_DATA FileInformation; // File information 
    int  dwError;   // Folder deleting error 
    std::string strPattern;   // Pattern 

    strPattern = (std::string)(refRootDirectory) + "\\*.*"; 
    hFile = ::FindFirstFile(strPattern.c_str(), &FileInformation); 

    if(hFile != INVALID_HANDLE_VALUE) 
    { 
     do { 
      if(FileInformation.cFileName[0] != '.') { 
       strFilePath.erase(); 
       strFilePath = std::string(refRootDirectory) + "\\" + FileInformation.cFileName; 

       if(FileInformation.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { 
        DeleteDirectory((char*)strFilePath.c_str()); 

        dwError = ::GetLastError(); 
        if(dwError != ERROR_NO_MORE_FILES) { 
         std::cout << "!ERROR!: [[" << strFilePath.c_str() << "]]\n"; 
         return dwError; 
        } else { 
         // Set directory attributes 
         if(! ::SetFileAttributes(refRootDirectory,FILE_ATTRIBUTE_NORMAL)) { 
          std::cout << "!ERROR!: [[" << strFilePath.c_str() << "]]\n"; 
          return ::GetLastError(); 
         } 

         // Delete directory 
         if(! ::RemoveDirectory(refRootDirectory)) { 
          std::cout << "!ERROR!: [[" << strFilePath.c_str() << "]]\n"; 
          return ::GetLastError(); 
         } 
        } 

        ++num_dirs; 
       } else { 

        // Set file attributes 
        if(! ::SetFileAttributes(strFilePath.c_str(),FILE_ATTRIBUTE_NORMAL)) { 
         std::cout << "!ERROR!: [[" << strFilePath.c_str() << "]]\n"; 
         return ::GetLastError(); 
        } 

        // Delete file 
        if (! ::DeleteFile(strFilePath.c_str())) { 
         std::cout << "!ERROR!: [[" << strFilePath.c_str() << "]]\n"; 
         return ::GetLastError(); 
        } 

        size_files.ull  += FileInformation.nFileSizeLow; 
        size_files.uint.high += FileInformation.nFileSizeHigh; 

        ++num_files; 
       } 
      } 
     } while(::FindNextFile(hFile,&FileInformation)); 

     // Close handle 
     ::FindClose(hFile ); 
    } 

    return 0; 
} 

unsigned long long num_files_total=0; 
unsigned long long num_dirs_total=0; 
unsigned long long total_size_files=0; 

void my_del_directory(char* dir_name) { 
    int iRC = DeleteDirectory(dir_name); 
    //int iRC=0; 

    std::cout << "\"" << dir_name << "\"" 
      "\n Folders: " << num_dirs 
      << "\n Files: " << num_files 
      << "\n Size: " << size_files.ull << " Bytes"; 
    if(iRC) 
    { 
     std::cout << "\n!ERROR!: " << iRC; 
    } 
    std::cout << "\n\n"; 

    num_dirs_total += num_dirs; 
    num_files_total += num_files; 
    total_size_files += size_files.ull; 
    num_dirs = 1; 
    num_files = 0; 
    size_files.ull = 0ULL; 
    return; 
} 

int main(void) 
{ 
    size_files.ull = 0ULL; 

    my_del_directory((char*)"C:\Windows\temp"  ); 
     // This will clear out the System temporary directory on windows systems 

    std::cout << "\n\nResults" << "\nTotal Folders: " << num_dirs_total 
        << "\nTotal Files: " << num_files_total 
        << "\nTotal Size: " << total_size_files << " Bytes\n"; 

    return 0; 
} 
+0

¿Por qué reenviar declara 'DeleteDirectory'? Lo declaras en dos líneas reales más abajo. – user4581301

3

con C++ 17 puede utilizar std::filesystem, en C++ 14 std::experimental::filesystem ya está disponible. Ambos permiten el uso de filesystem::remove().

C++ 17:

#include <filesystem> 
std::filesystem::path::remove("myEmptyDirectoryOrFile"); // Deletes empty directories or single files. 
std::filesystem::path::remove_all("myDirectory"); // Deletes one or more files recursively. 

C++ 14:

#include <experimental/filesystem> 
std::experimental::filesystem::path::remove("myDirectory"); 

Nota 1: Esas funciones tiran filesystem_error en caso de errores. Si quiere evitar la captura de excepciones, utilice las variantes sobrecargadas con std::error_code como segundo parámetro. P.ej.

std::error_code errorCode; 
if (!std::filesystem::path::remove("myEmptyDirectoryOrFile", errorCode)) { 
    std::cout << errorCode.message() << std::endl; 
} 

Nota 2: La conversión a std::filesystem::path sucede implícita de diferentes codificaciones, por lo que puede pasar cadenas de filesystem::remove().

Cuestiones relacionadas