Как удалить каталог рекурсивно? - PullRequest
5 голосов
/ 23 марта 2012

RemoveDirectory (); Удаляет только пустой каталог, но как удалить каталоги, в которых есть файлы?

Ответы [ 5 ]

7 голосов
/ 23 марта 2012

Лучшее решение, если вы можете его использовать, это boost::filesystem::remove_all. Таким образом, вам не нужно беспокоиться о платформе. Я не знаю ни одного другого независимого от платформы решения; в противном случае обычным способом будет считывание каталога и его рекурсивное уменьшение (но при чтении каталога также используется boost::filesystem или системно-зависимый код).

4 голосов
/ 23 марта 2012

Если вы готовы использовать Windows API, то самый простой способ сделать это - позвонить SHFileOperation. Используйте операцию FO_DELETE и не забудьте завершить двойное нулевое имя вашего каталога.

3 голосов
/ 23 марта 2012

Это может быть неудачно, но рассмотрите возможность использования

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

Это уродливо, но это слишком просто игнорировать.Он также имеет все "как работать с файлами на сетевых ресурсах".Какое бы решение вы ни предложили, это, вероятно, (неполное и / или неправильное) переопределение rd, поэтому вызов внешнего процесса на самом деле был бы хорошим повторным использованием кода.; -)

3 голосов
/ 23 марта 2012

Обычно, если библиотечный метод недоступен, это делается с помощью рекурсии.Функция выполняет итерацию всех записей каталога, удаляя «обычные» файлы и вызывая себя с любым найденным путем к каталогу.Это разрушает целые деревья каталогов (в моей версии Windows есть явные проверки пройденного пути, чтобы предотвратить разрушение папок ОС в случае случайной передачи суицидального параметра).

2 голосов
/ 16 сентября 2017

Согласно 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, кроме вопросов безопасности, он был заменен IFileOperation начиная с Windows Vista.

Надеюсь, это поможет!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...