2009-04-09 21 views
26

Come posso cancellare una cartella usando C++?Come eliminare una cartella in C++?

Se non esiste una modalità multipiattaforma, quindi come farlo per i sistemi operativi più popolari: Windows, Linux, Mac, iOS, Android? Una soluzione POSIX funzionerebbe per tutti loro?

risposta

0

Lo standard C++ definisce la funzione remove(), che può o non può eliminare una cartella, a seconda dell'implementazione. In caso contrario, è necessario utilizzare una funzione specifica di implementazione come rmdir().

4

La directory deve essere vuota e il programma deve avere le autorizzazioni per eliminare lo

ma la funzione chiamata rmdir lo farà

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

Quale file di intestazione si utilizza in Windows? –

+0

utilizza _rmdir per Windows e l'intestazione è '#include ' Credo, uguale a _mkdir – Mich

8

La directory dovrebbe essere vuota.

BOOL RemoveDirectory(LPCTSTR lpPathName); 
+12

Questo è solo Windows, penso? Trovo strano che Vinay abbia un avatar Apple, ma pubblica una risposta specifica per Windows. ;) – Aardvark

+9

Vinay non ha più avatar Apple;) – sergtk

+3

Vinay ha un avatar Android ora :) –

-2

Se si utilizza Windows, quindi dare un'occhiata a this link. Altrimenti, puoi cercare la tua versione specifica del sistema operativo. Non penso che C++ abbia un modo multipiattaforma per farlo. Alla fine, non è il lavoro di C++, è il lavoro del sistema operativo.

16

eliminare la cartella (sub_folders e file) in Windows (VisualC++) non utilizzando le API di Shell, per il campione di lavoro migliore:

#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; 
} 

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

+4

Grazie per aver pubblicato qualcosa che non era Boost o una chiamata al sistema(). –

+0

Ma un giorno il collegamento sarà morto. Hai intenzione di includere il codice pertinente nella risposta? – jogojapan

+0

Sembra che questa soluzione possa fallire a causa delle razze del filesystem: DeleteFile non è atomico, il che significa che l'eliminazione della directory che lo contiene può fallire perché la directory non è (ancora) vuota. Questo discorso spiega in dettaglio il problema e offre un modo più sicuro per eliminare una directory/albero su Windows: https://www.youtube.com/watch?v=uhRWMGBjlO8 –

0

// per Windows:

#include <direct.h> 


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

Questo non funziona per i percorsi Unicode. Non è utile nella maggior parte delle applicazioni moderne. – strcat

5

Usa SHFileOperation per rimuovere la cartella recursivelly

2

si può anche provare questo se siete su Linux:

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

Il miglior approccio per Android, thx. –

0

Prova sistema di utilizzo "rmdir -s -q file_to_delte" .
Questo cancellerà la cartella e tutti i file in essa contenuti.

+1

In POSIX, non lo farà: non c'è il flag '-s' lì. Su Windows, questo tenta di rimuovere le directory '-s' e' -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

se 'percorso' finisce con un '/' allora solo il/content/dovrebbe essere cancellato e la directory - now empty - dovrebbe rimanere; anche 'if (* (entry-> d_name)! = '.')' dovrebbe cercare "." e "..", il modo in cui è attualmente non eliminerà i file nascosti. altrimenti è fantastico – slashmais

0

La mia implementazione basata su hB0 consente anche di visualizzare il numero di file in ogni cartella con un piccolo aumento di prestazioni.

#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

Perché avanti dichiarare 'DeleteDirectory'? Lo dichiari per due linee reali più in basso. – user4581301

3

Con C++ 17 è possibile utilizzare std::filesystem, in C++ 14 std::experimental::filesystem è già disponibile. Entrambi consentono l'utilizzo di 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: Tali funzioni gettano filesystem_error in caso di errori. Se si desidera evitare di rilevare eccezioni, utilizzare le varianti sovraccaricate con std::error_code come secondo parametro. Per esempio.

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

Nota 2: La conversione in std::filesystem::path accade implicita da diverse codifiche, in modo da poter passare le stringhe a filesystem::remove().

Problemi correlati