2012-03-23 88 views
5

RemoveDirectory();只刪除空目錄,但如何刪除裏面有文件的目錄?如何遞歸移除目錄?

+0

在什麼平臺上? – 2012-03-23 10:55:57

+0

@OliCharlesworth先生,在Windows XP – 2012-03-23 10:57:20

+0

你嘗試了什麼? – Nawaz 2012-03-23 11:00:37

回答

4

如果您準備使用Windows API,那麼完成此操作的最簡單方法是致電SHFileOperation。使用FO_DELETE操作,並且不要忘記將空白終止您的目錄名稱。

+0

請記住,SHFileOperation適用於用戶模式應用程序,但在從Windows服務中調用時無效,尤其是在使用模擬刪除UNC網絡共享上的目錄時。 對於這種情況,你需要做的工作,並用DeleteFile()/ RemoveDirectory()困難的方式使用FindFirstFile()/ FindNext() – WebDrive 2015-03-04 20:47:38

3

通常,如果沒有庫方法可用,則通過遞歸完成。一個函數迭代所有的目錄條目,刪除'普通'文件,並用找到的任何目錄路徑調用它自己。這破壞了整個目錄樹,(我的Windows版本對傳遞的路徑進行了顯式檢查,以防止在意外傳入自殺參數的情況下破壞操作系統文件夾)。

2

這可能是瘸腿的,但可以考慮使用

system("rd /s /q ..."); 

這是醜陋的,但它太簡單,不容忽視。它還包含所有「如何處理網絡共享上的文件」的內容。無論你提出的解決方案可能是(不完整的和/或不正確的)rd的重新實現,所以調用外部過程實際上是很好的代碼重用。 ;-)

+0

代碼重用和不可移植性,如果不存在編譯錯誤。對於一個非常小的程序,這可能是有用和正確的,對於長壽命的大型項目來說,可能更少。就我個人而言,我會一直檢查這個命令是否真的存在。 – 2012-03-23 11:26:00

+0

@phresnel:問題僅適用於Windows系統,默認情況下,所有Windows系統都可以使用'rd'。我認爲'rd'可用比'SHFileOperation'更有可能('SHFileOperation'只有在Windows XP以後纔出現,並且它已被Windows Vista棄用)。 – 2012-03-23 11:36:41

+0

這個概率與我的關係不大。就個人而言,如果某些功能不存在,我不會編譯時錯誤;系統永遠不會有編譯時錯誤。如上所述,對於小型系統特定的程序,這可能沒問題。但我會建議大型或長期生活的節目。你從未知道在5,10,15年後會發生什麼。如果突然間每個人都會切換到Mac或Linux,那麼您肯定會希望您的現金牛在該平臺上運行。 – 2012-03-23 11:56:15

7

最好的解決方案,如果你可以使用它,是boost::filesystem::remove_all。這樣,你不必擔心平臺特定的東西。我不知道有任何其他平臺獨立解決方案;否則通常的方式將涉及讀取目錄,並遞歸降序(但是讀取目錄的方式也使用boost::filesystem或系統相關代碼)。

2

根據MSDN,與相對路徑一起使用時,SHFileOperation不是線程安全的。它只能安全​​地使用絕對路徑。

我建議使用此代碼來代替:

double directory_delete(char *pathname) 
{ 
    string str(pathname); 
    if (!str.empty()) 
    { 
     while (*str.rbegin() == '\\' || *str.rbegin() == '/') 
     { 
      str.erase(str.size()-1); 
     } 
    } 
    replace(str.begin(),str.end(),'/','\\'); 

    struct stat sb; 
    if (stat((char *)str.c_str(),&sb) == 0 && 
     S_ISDIR(sb.st_mode)) 
    { 
      HANDLE hFind; 
      WIN32_FIND_DATA FindFileData; 

      TCHAR DirPath[MAX_PATH]; 
      TCHAR FileName[MAX_PATH]; 

      _tcscpy(DirPath,(char *)str.c_str()); 
      _tcscat(DirPath,"\\*"); 
      _tcscpy(FileName,(char *)str.c_str()); 
      _tcscat(FileName,"\\"); 

      hFind = FindFirstFile(DirPath,&FindFileData); 
      if (hFind == INVALID_HANDLE_VALUE) return 0; 
      _tcscpy(DirPath,FileName); 

      bool bSearch = true; 
      while (bSearch) 
      { 
       if (FindNextFile(hFind,&FindFileData)) 
       { 
        if (!(_tcscmp(FindFileData.cFileName,".") && 
         _tcscmp(FindFileData.cFileName,".."))) continue; 
        _tcscat(FileName,FindFileData.cFileName); 
        if ((FindFileData.dwFileAttributes & 
        FILE_ATTRIBUTE_DIRECTORY)) 
        { 
         if (!directory_delete(FileName)) 
         { 
          FindClose(hFind); 
          return 0; 
         } 
         RemoveDirectory(FileName); 
         _tcscpy(FileName,DirPath); 
        } 
        else 
        { 
         if (FindFileData.dwFileAttributes & 
          FILE_ATTRIBUTE_READONLY) 
          _chmod(FileName, _S_IWRITE); 

         if (!DeleteFile(FileName)) 
         { 
          FindClose(hFind); 
          return 0; 
         } 
         _tcscpy(FileName,DirPath); 
        } 
       } 
       else 
       { 
        if (GetLastError() == ERROR_NO_MORE_FILES) 
         bSearch = false; 
        else 
        { 
         FindClose(hFind); 
         return 0; 
        } 
       } 
      } 
      FindClose(hFind); 

      return (double)(RemoveDirectory((char *)str.c_str()) == true); 
    } 
    else 
    { 
     return 0; 
    } 
} 

如果你想用我的代碼「原樣」,您將需要這些標題,並在你的CPP文件的頂部,例如:

#include <windows.h> // winapi 
#include <sys/stat.h> // stat 
#include <tchar.h> // _tcscpy,_tcscat,_tcscmp 
#include <string> // string 
#include <algorithm> // replace 

using namespace std; 

......我想就是這樣。

我的代碼是基於這篇文章:

http://www.codeguru.com/cpp/w-p/files/folderdirectorymaintenance/article.php/c8999/Deleting-a-Directory-Along-with-SubFolders.htm

我強烈建議永遠不要使用SHFileOperation,除了安全問題,這是因爲Windows Vista中取代IFileOperation。

希望這會有所幫助!