RemoveDirectory();只刪除空目錄,但如何刪除裏面有文件的目錄?如何遞歸移除目錄?
回答
如果您準備使用Windows API,那麼完成此操作的最簡單方法是致電SHFileOperation
。使用FO_DELETE
操作,並且不要忘記將空白終止您的目錄名稱。
請記住,SHFileOperation適用於用戶模式應用程序,但在從Windows服務中調用時無效,尤其是在使用模擬刪除UNC網絡共享上的目錄時。 對於這種情況,你需要做的工作,並用DeleteFile()/ RemoveDirectory()困難的方式使用FindFirstFile()/ FindNext() – WebDrive 2015-03-04 20:47:38
通常,如果沒有庫方法可用,則通過遞歸完成。一個函數迭代所有的目錄條目,刪除'普通'文件,並用找到的任何目錄路徑調用它自己。這破壞了整個目錄樹,(我的Windows版本對傳遞的路徑進行了顯式檢查,以防止在意外傳入自殺參數的情況下破壞操作系統文件夾)。
這可能是瘸腿的,但可以考慮使用
system("rd /s /q ...");
這是醜陋的,但它太簡單,不容忽視。它還包含所有「如何處理網絡共享上的文件」的內容。無論你提出的解決方案可能是(不完整的和/或不正確的)rd
的重新實現,所以調用外部過程實際上是很好的代碼重用。 ;-)
代碼重用和不可移植性,如果不存在編譯錯誤。對於一個非常小的程序,這可能是有用和正確的,對於長壽命的大型項目來說,可能更少。就我個人而言,我會一直檢查這個命令是否真的存在。 – 2012-03-23 11:26:00
@phresnel:問題僅適用於Windows系統,默認情況下,所有Windows系統都可以使用'rd'。我認爲'rd'可用比'SHFileOperation'更有可能('SHFileOperation'只有在Windows XP以後纔出現,並且它已被Windows Vista棄用)。 – 2012-03-23 11:36:41
這個概率與我的關係不大。就個人而言,如果某些功能不存在,我不會編譯時錯誤;系統永遠不會有編譯時錯誤。如上所述,對於小型系統特定的程序,這可能沒問題。但我會建議大型或長期生活的節目。你從未知道在5,10,15年後會發生什麼。如果突然間每個人都會切換到Mac或Linux,那麼您肯定會希望您的現金牛在該平臺上運行。 – 2012-03-23 11:56:15
最好的解決方案,如果你可以使用它,是boost::filesystem::remove_all
。這樣,你不必擔心平臺特定的東西。我不知道有任何其他平臺獨立解決方案;否則通常的方式將涉及讀取目錄,並遞歸降序(但是讀取目錄的方式也使用boost::filesystem
或系統相關代碼)。
根據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;
......我想就是這樣。
我的代碼是基於這篇文章:
我強烈建議永遠不要使用SHFileOperation,除了安全問題,這是因爲Windows Vista中取代IFileOperation。
希望這會有所幫助!
- 1. Howto在Meteor中遞歸移除目錄?
- 2. 如何刪除一個目錄遞歸
- 3. emacs遞歸刪除目錄?
- 4. 遞歸刪除目錄
- 5. 遞歸地刪除目錄
- 6. 遞歸刪除目錄
- 7. 目錄遞歸
- 8. 遞歸目錄SVN移動shell腳本
- 9. 遞歸移除目錄和文件的問題
- 10. 延遲時刪除目錄遞歸
- 11. 遞歸刪除目錄用C
- 12. 遞歸地scp除當前目錄外
- 13. Ruby遞歸目錄
- 14. java.lang.StackOverflowError遞歸目錄
- 15. 如何用Perl或shell非遞歸地遷移目錄?
- 16. 如何遞歸安裝目錄與WAF
- 17. 如何include目錄遞歸NuSpec文件
- 18. 如何遞歸地重命名目錄
- 19. Python IOError:[遞歸目錄2]來自遞歸目錄調用
- 20. 移除左遞歸從CFG
- 21. 移除元件遞歸
- 22. 如何遞歸複製目錄內容並排除源目錄本身?
- 23. Ruby:我如何遞歸查找和刪除空目錄?
- 24. 如何遞歸刪除以「xxxxx」開頭的目錄?
- 25. 如何使用Perl遞歸刪除所有.svn目錄?
- 26. 如何使用grep在遞歸搜索中排除目錄?
- 27. 如何遞歸監視除了使用inotify以外的目錄
- 28. 保持目錄和所有子目錄遞歸除了文件
- 29. 刪除Unix中的遞歸目錄(無限子目錄)
- 30. C目錄和子目錄遞歸
在什麼平臺上? – 2012-03-23 10:55:57
@OliCharlesworth先生,在Windows XP – 2012-03-23 10:57:20
你嘗試了什麼? – Nawaz 2012-03-23 11:00:37