c ++ - Sådan fjernes bibliotek rekursivt?

Indlæg af Hanne Mølgaard Plasc

Problem



RemoveDirectory (); Fjerner kun tom mappe, men hvordan fjerner man mapper, der har filer inde?

Bedste reference


Hvis du er parat til at bruge Windows API, så er den nemmeste måde at få dette gjort på at ringe SHFileOperation. Brug FO\_DELETE operationen og glem ikke at fordoble dit katalognavn. [9]

Andre referencer 1


Den bedste løsning, hvis du kan bruge den, er boost::filesystem::remove\_all. På den måde behøver du ikke bekymre dig om de platformspecifikke ting. Jeg er ikke opmærksom på nogen anden platformsafhængig løsning; den sædvanlige måde ellers ville indebære at læse mappen og rekursivt nedstigende den (men vejen til læsning af mappen bruger også boost::filesystem eller systemafhængig kode). [10]

Andre referencer 2


Typisk, hvis der ikke findes nogen biblioteksmetode, gøres dette ved rekursion. En funktion gentager alle mappeposter, sletter 'almindelige' filer og kalder sig selv med en hvilken som helst mappebane, der findes. Dette ødelægger hele katalogtræer, (min Windows-version har eksplicit kontroller på den vej, der er gået for at forhindre, at den ødelægger OS-mapper, hvis der tilfældigvis overføres en selvmordsparameter).

Andre referencer 3


Dette kan være lam, men overveje at bruge


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


Det er grimt, men det er for nemt at ignorere. Det har også alle de 'hvordan man håndterer filer på netværksandele', der er udarbejdet. Uanset hvilken løsning du oplever, er det sandsynligvis en (ufuldstændig og/eller ukorrekt) genimplementering af rd, så det ville være en god kodegenbrug at kalde op til den eksterne proces. ;-)

Andre referencer 4


Ifølge MSDN er SHFileOperation ikke tråd sikker, når den bruges sammen med relative stier. Det kan kun bruges sikkert med absolutte stier.


Jeg anbefaler at bruge denne kode i stedet:


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


Hvis du vil bruge min kode 'as-is', skal du bruge disse overskrifter og lignende øverst i din cpp-fil:


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

using namespace std;


... og jeg tror det er det.


Min kode er baseret på denne artikel:


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


Jeg anbefaler på det kraftigste aldrig at bruge SHFileOperation, bortset fra sikkerhedsproblemer, blev det erstattet af IFileOperation siden Windows Vista.


Håber dette hjælper!