如何递归删除目录

How do I remove a directory recursively?

本文关键字:删除目录 递归 何递归      更新时间:2023-10-16

RemoveDirectory()仅删除空目录。如何删除包含文件的目录?

由于C++17,最好的解决方案是std::filesystem::remove_all。在此之前,您可以使用Boost实现boost::filesystem::remove_all。无论哪种方式,您都不必担心特定于平台的东西。

我不知道有任何其他独立于平台的解决方案;否则,通常的方法将包括读取目录,并递归递减(但读取目录的方法也使用std::filesystemboost::filesystem或系统相关代码)。

如果您准备使用Windows API,那么最简单的方法就是调用SHFileOperation。使用FO_DELETE操作,不要忘记使用双null终止目录名。

通常,如果没有可用的库方法,则通过递归来完成。函数迭代所有目录条目,删除"普通"文件,并使用找到的任何目录路径调用自己。这会破坏整个目录树(我的Windows版本对传递的路径进行了明确的检查,以防止意外传递自杀参数时破坏操作系统文件夹)。

根据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取代。

这可能很蹩脚,但请考虑使用

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

它很丑陋,但它太简单了,不容忽视。它还解决了所有"如何处理网络共享上的文件"的问题。无论你想出什么解决方案,都可能是对rd的(不完整和/或不正确的)重新实现,所以调用外部进程实际上是很好的代码重用