54

如何使用 C++ 删除文件夹?

如果不存在跨平台方式,那么对于最流行的操作系统——Windows、Linux、Mac、iOS、Android,如何做到这一点?POSIX 解决方案是否适用于所有人?

4

17 回答 17

63

我强烈建议使用 Boost.FileSystem。

http://www.boost.org/doc/libs/1_38_0/libs/filesystem/doc/index.htm

在你的情况下,那将是

boost::filesystem::remove_all(yourPath)

于 2009-04-09T15:36:35.333 回答
55

使用 C++17 可以使用std::filesystem,在 C++14std::experimental::filesystem中已经可用。两者都允许使用filesystem::remove().

C++17:

#include <filesystem>
std::filesystem::remove("myEmptyDirectoryOrFile"); // Deletes empty directories or single files.
std::filesystem::remove_all("myDirectory"); // Deletes one or more files recursively.

C++14:

#include <experimental/filesystem>
std::experimental::filesystem::remove("myDirectory");

注意 1:如果出现错误,这些函数会抛出filesystem_error。如果您想避免捕获异常,请使用重载变体std::error_code作为第二个参数。例如

std::error_code errorCode;
if (!std::filesystem::remove("myEmptyDirectoryOrFile", errorCode)) {
    std::cout << errorCode.message() << std::endl;
}

注意 2:转换为std::filesystem::path隐式地发生在不同的编码中,因此您可以将字符串传递给filesystem::remove().

于 2017-04-13T12:58:30.537 回答
23

在不使用 Shell API 的 Windows (VisualC++) 中删除文件夹(子文件夹和文件),这是最好的工作示例:

#include <string>
#include <iostream>

#include <windows.h>
#include <conio.h>


int DeleteDirectory(const std::string &refcstrRootDirectory,
                    bool              bDeleteSubdirectories = true)
{
  bool            bSubdirectory = false;       // Flag, indicating whether
                                               // subdirectories have been found
  HANDLE          hFile;                       // Handle to directory
  std::string     strFilePath;                 // Filepath
  std::string     strPattern;                  // Pattern
  WIN32_FIND_DATA FileInformation;             // File information


  strPattern = refcstrRootDirectory + "\\*.*";
  hFile = ::FindFirstFile(strPattern.c_str(), &FileInformation);
  if(hFile != INVALID_HANDLE_VALUE)
  {
    do
    {
      if(FileInformation.cFileName[0] != '.')
      {
        strFilePath.erase();
        strFilePath = refcstrRootDirectory + "\\" + FileInformation.cFileName;

        if(FileInformation.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
        {
          if(bDeleteSubdirectories)
          {
            // Delete subdirectory
            int iRC = DeleteDirectory(strFilePath, bDeleteSubdirectories);
            if(iRC)
              return iRC;
          }
          else
            bSubdirectory = true;
        }
        else
        {
          // Set file attributes
          if(::SetFileAttributes(strFilePath.c_str(),
                                 FILE_ATTRIBUTE_NORMAL) == FALSE)
            return ::GetLastError();

          // Delete file
          if(::DeleteFile(strFilePath.c_str()) == FALSE)
            return ::GetLastError();
        }
      }
    } while(::FindNextFile(hFile, &FileInformation) == TRUE);

    // Close handle
    ::FindClose(hFile);

    DWORD dwError = ::GetLastError();
    if(dwError != ERROR_NO_MORE_FILES)
      return dwError;
    else
    {
      if(!bSubdirectory)
      {
        // Set directory attributes
        if(::SetFileAttributes(refcstrRootDirectory.c_str(),
                               FILE_ATTRIBUTE_NORMAL) == FALSE)
          return ::GetLastError();

        // Delete directory
        if(::RemoveDirectory(refcstrRootDirectory.c_str()) == FALSE)
          return ::GetLastError();
      }
    }
  }

  return 0;
}


int main()
{
  int         iRC                  = 0;
  std::string strDirectoryToDelete = "c:\\mydir";


  // Delete 'c:\mydir' without deleting the subdirectories
  iRC = DeleteDirectory(strDirectoryToDelete, false);
  if(iRC)
  {
    std::cout << "Error " << iRC << std::endl;
    return -1;
  }

  // Delete 'c:\mydir' and its subdirectories
  iRC = DeleteDirectory(strDirectoryToDelete);
  if(iRC)
  {
    std::cout << "Error " << iRC << std::endl;
    return -1;
  }

  // Wait for keystroke
  _getch();

  return 0;
}

来源:http ://www.codeguru.com/forum/showthread.php?t=239271

于 2012-05-31T15:03:42.387 回答
10

目录应该是空的。

BOOL RemoveDirectory( LPCTSTR lpPathName );
于 2009-04-09T15:32:09.387 回答
9
void remove_dir(char *path)
{
        struct dirent *entry = NULL;
        DIR *dir = NULL;
        dir = opendir(path);
        while(entry = readdir(dir))
        {   
                DIR *sub_dir = NULL;
                FILE *file = NULL;
                char abs_path[100] = {0};
                if(*(entry->d_name) != '.')
                {   
                        sprintf(abs_path, "%s/%s", path, entry->d_name);
                        if(sub_dir = opendir(abs_path))
                        {   
                                closedir(sub_dir);
                                remove_dir(abs_path);
                        }   
                        else 
                        {   
                                if(file = fopen(abs_path, "r"))
                                {   
                                        fclose(file);
                                        remove(abs_path);
                                }   
                        }   
                }   
        }   
        remove(path);
}
于 2014-12-22T14:02:58.363 回答
5

Use SHFileOperation to remove the folder recursivelly

于 2012-11-06T17:28:21.933 回答
4

该目录必须为空,并且您的程序必须具有删除它的权限

但是名为 rmdir 的函数会做到这一点

rmdir("C:/Documents and Settings/user/Desktop/itsme") 
于 2009-04-09T15:31:25.253 回答
3

如果你在 linux 上,你也可以试试这个:

system("rm -r path");
于 2013-01-08T06:54:01.223 回答
2

这适用于删除目录中的所有目录和文件。

#include <iostream>
#include <cstring>
#include <cstdlib>
using namespace std;
int main()
{
    cout << "Enter the DirectoryName to Delete : ";
    string directoryName;
    cin >> directoryName;
    string a = "rmdir /s /q " + directoryName;
    system(a.c_str());
    return 0;
}
于 2020-02-02T19:36:52.460 回答
1

C++ 标准定义了 remove() 函数,它可能会也可能不会删除文件夹,具体取决于实现。如果不需要,则需要使用特定于实现的函数,例如 rmdir()。

于 2009-04-09T15:29:33.713 回答
1

我没有评论的“声誉”,所以我必须做出回答。

据我所见,以前的 Windows 解决方案包含一个错误(在检查“.”时:它不会删除像 .ssh 这样的目录)。

此外,缺少 UTF-8 路径的(现在必须的)管理。

// OK we want the UTF-8 compatible functions
#ifndef UNICODE
#define UNICODE
#endif

#include <stdio.h>
#include <windows.h>
#include <string>
#include <assert.h>


// 16bit wide string to UTF-8 
std::string wtou(const wchar_t* i_string) 
{
    assert(sizeof(wchar_t)==2);     // Not always true 
    assert((wchar_t)(-1)==65535);   // not too big
    std::string myresult;
    if (!i_string) 
        return myresult;
    for (; *i_string; i_string++) 
    {
        if (*i_string<128) 
            myresult+=*i_string;
        else 
        if (*i_string<2048) 
            myresult+=192+*i_string/64, myresult+=128+*i_string%64;
        else 
            myresult+=224+*i_string/4096, myresult+=128+*i_string/64%64, myresult+=128+*i_string%64;
    }
    return myresult;
}

// UTF-8 to wide string
std::wstring utow(const char* i_string) 
{
    assert(sizeof(wchar_t)==2);
    assert((wchar_t)(-1)==65535);
    std::wstring myresult;
    if (!i_string) 
        return myresult;
    const unsigned char* s=(const unsigned char*)i_string;
    for (; s && *s; s++) 
    {
        if (s[0]<128) 
            myresult+=s[0];
        else 
        if (s[0]>=192 && s[0]<224 && s[1]>=128 && s[1]<192)
            myresult+=(s[0]-192)*64+s[1]-128, ++i_string;
        else 
        if (s[0]>=224 && s[0]<240 && s[1]>=128 && s[1]<192 && s[2]>=128 && s[2]<192)
            myresult+=(s[0]-224)*4096+(s[1]-128)*64+s[2]-128, s+=2;
    }
    return myresult;
}

int win_erredbarras(const std::string &i_path,bool i_flagrecursive=true)
{
    bool    flagdebug=true;
    bool    flagsubdir=false;
    HANDLE  myhandle;
    std::wstring wfilepath;
    WIN32_FIND_DATA findfiledata;

    std::string pattern=i_path+"\\*.*";
  
    std::wstring wpattern   =utow(pattern.c_str());
    std::wstring wi_path    =utow(i_path.c_str());

    myhandle=FindFirstFile(wpattern.c_str(),&findfiledata);
  
    if (myhandle!=INVALID_HANDLE_VALUE)
    {
        do
        {
            std::string t=wtou(findfiledata.cFileName);
            
            if ((t!=".") && (t!=".."))
            {
                wfilepath=wi_path+L"\\"+findfiledata.cFileName;
                if (findfiledata.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
                {
                    if (i_flagrecursive)
                    {
                        const std::string temp(wfilepath.begin(),wfilepath.end());
                        if (flagdebug)
                            printf("\n\nDelete directory   %s\n",temp.c_str());
                        int myresult=win_erredbarras(temp,i_flagrecursive);
                        if (myresult)
                            return myresult;
                    }
                    else
                        flagsubdir=true;
                }
                else
                {
                    const std::string ttemp(wfilepath.begin(), wfilepath.end() );
                    if (flagdebug)
                        printf("Try to delete file %s\n",ttemp.c_str());

                    if (SetFileAttributes(wfilepath.c_str(),FILE_ATTRIBUTE_NORMAL) == FALSE)
                    {
                        if (flagdebug)
                            printf("31019: ERROR cannot change attr of file %s\n",ttemp.c_str());
                        return GetLastError();
                    }
                    
                    if (DeleteFile(wfilepath.c_str())==FALSE)
                    {
                        if (flagdebug)
                            printf("31025: ERROR highlander file %s\n",ttemp.c_str());
                        return GetLastError();
                    }
                }
            }
        } while(FindNextFile(myhandle,&findfiledata)==TRUE);

        FindClose(myhandle);

        DWORD myerror=GetLastError();
        if (myerror==ERROR_NO_MORE_FILES)
        {
            if (!flagsubdir)
            {
                const std::string dtemp(wi_path.begin(), wi_path.end());
                
                if (flagdebug)
                    printf("Delete no subdir   %s\n",dtemp.c_str());
                            
                if (SetFileAttributes(wi_path.c_str(),FILE_ATTRIBUTE_NORMAL)==FALSE)
                {
                    if (flagdebug)
                        printf("30135: ERROR cannot change folder attr %s\n",dtemp.c_str());
                    return GetLastError();
                }
                                
                if (RemoveDirectory(wi_path.c_str())==FALSE)
                {
                    if (flagdebug)
                        printf("31047: ERROR highlander dir %s\n",dtemp.c_str());
                    return GetLastError();
                }
            }
        }
        else
            return myerror;
    }
    return 0;
}

int main()
{
    win_erredbarras("z:\\knb",true);
    return 0;
}

现在我放了一个 UNIX/Linux 版本,基于以前固定的功能

#include <stdio.h>
#include <string>
#include <dirent.h>
#include <sys/stat.h>

/// secondary functions to be #ifdeffed on Windows
bool isdirectory(std::string i_filename)
{
    if (i_filename.length()==0)
        return false;
    else
        return i_filename[i_filename.size()-1]=='/';
}
bool delete_file(const char* i_filename) 
{
    return remove(i_filename)==0;
}
bool delete_dir(const char* i_directory) 
{
    return remove(i_directory)==0;
}

int erredbarras(const std::string &i_path,bool i_flagrecursive=true)
{
    bool    flagdebug=true;
    bool    risultato=false;

    DIR *d=opendir(i_path.c_str());

    if (d) 
    {
        struct dirent *p;
        risultato=true;
        while (risultato && (p=readdir(d))) 
        {
            if (!strcmp(p->d_name, ".") || !strcmp(p->d_name, ".."))
                continue;
            bool risultato2=false;
            struct stat statbuf;
            
            std::string temp;
            if (isdirectory(i_path))
                temp=i_path+p->d_name;
            else
                temp=i_path+"/"+p->d_name;

            if (!stat(temp.c_str(), &statbuf)) 
            {
                if (S_ISDIR(statbuf.st_mode))
                    risultato2=erredbarras(temp);
                else
                {
                    if (flagdebug)
                        printf("Delete file %s\n",temp.c_str());
                    risultato2=delete_file(temp.c_str());
                }
            }
            risultato=risultato2;
        }
        closedir(d);
    }

    if (risultato)
    {
        if (flagdebug)
            printf("Delete dir  %s\n\n",i_path.c_str());
        delete_dir(i_path.c_str());
    }
   return risultato;
}


int main()
{
    printf("Risultato %d\n",erredbarras("/tmp/knb/"));
    return 0;
}
于 2021-06-10T12:15:06.737 回答
0

尝试使用系统“ rmdir -s -q file_to_delte”。
这将删除文件夹及其中的所有文件。

于 2013-02-26T08:48:48.677 回答
0

//对于窗口:

#include <direct.h>


if(_rmdir("FILEPATHHERE") != -1)
{
  //success     
} else {
  //failure
}
于 2012-06-01T03:02:07.647 回答
0

如果您使用的是Poco库,这是一种删除目录的可移植方法。

#include "Poco/File.h"
...
...
Poco::File fooDir("/path/to/your/dir");
fooDir.remove(true);

使用“true”调用的 remove 函数意味着递归删除目录中的所有文件和子目录。

于 2019-06-07T03:34:21.183 回答
0

对于 linux(我在上面的代码中修复了错误):

void remove_dir(char *path)
{
        struct dirent *entry = NULL;
        DIR *dir = NULL;
        dir = opendir(path);
        while(entry = readdir(dir))
        {   
                DIR *sub_dir = NULL;
                FILE *file = NULL;
                char* abs_path new char[256];
                 if ((*(entry->d_name) != '.') || ((strlen(entry->d_name) > 1) && (entry->d_name[1] != '.')))
                {   
                        sprintf(abs_path, "%s/%s", path, entry->d_name);
                        if(sub_dir = opendir(abs_path))
                        {   
                                closedir(sub_dir);
                                remove_dir(abs_path);
                        }   
                        else 
                        {   
                                if(file = fopen(abs_path, "r"))
                                {   
                                        fclose(file);
                                        remove(abs_path);
                                }   
                        }   
                }
                delete[] abs_path;   
        }   
        remove(path);
}

对于窗户:

void remove_dir(const wchar_t* folder)
{
    std::wstring search_path = std::wstring(folder) + _T("/*.*");
    std::wstring s_p = std::wstring(folder) + _T("/");
    WIN32_FIND_DATA fd;
    HANDLE hFind = ::FindFirstFile(search_path.c_str(), &fd);
    if (hFind != INVALID_HANDLE_VALUE) {
        do {
            if (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
                if (wcscmp(fd.cFileName, _T(".")) != 0 && wcscmp(fd.cFileName, _T("..")) != 0)
                {
                    remove_dir((wchar_t*)(s_p + fd.cFileName).c_str());
                }
            }
            else {
                DeleteFile((s_p + fd.cFileName).c_str());
            }
        } while (::FindNextFile(hFind, &fd));
        ::FindClose(hFind);
        _wrmdir(folder);
    }
}
于 2018-06-08T17:44:55.063 回答
0

我自己的实现基于 hB0,它还允许您查看每个文件夹中的文件数量,同时也提高了一点性能。

#include <string>
#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <windows.h>
#include <conio.h>

union seperated {
  struct {
    unsigned int low;
    unsigned int high;
  } uint;
  unsigned long long ull;
};

unsigned long long num_dirs  = 1;
unsigned long long num_files = 0;
seperated size_files;

int DeleteDirectory( char* refRootDirectory );      //predeclare it

int DeleteDirectory( char* refRootDirectory ) {
    HANDLE      hFile;              // Handle to directory
    std::string strFilePath;            // Filepath
    WIN32_FIND_DATA FileInformation;    // File information
    int     dwError;            // Folder deleting error
    std::string strPattern;         // Pattern

    strPattern = (std::string)(refRootDirectory) + "\\*.*";
    hFile = ::FindFirstFile( strPattern.c_str(), &FileInformation );

    if( hFile != INVALID_HANDLE_VALUE )
    {
        do {
            if( FileInformation.cFileName[0] != '.' ) {
                strFilePath.erase();
                strFilePath = std::string(refRootDirectory) + "\\" + FileInformation.cFileName;

                if( FileInformation.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY ) {
                    DeleteDirectory( (char*)strFilePath.c_str() );

                    dwError = ::GetLastError();
                    if( dwError != ERROR_NO_MORE_FILES ) {
                        std::cout << "!ERROR!: [[" << strFilePath.c_str() << "]]\n";
                        return dwError;
                    } else {
                        // Set directory attributes
                        if( ! ::SetFileAttributes(refRootDirectory,FILE_ATTRIBUTE_NORMAL) ) {
                            std::cout << "!ERROR!: [[" << strFilePath.c_str() << "]]\n";
                            return ::GetLastError();
                        }

                        // Delete directory
                        if( ! ::RemoveDirectory(refRootDirectory) ) {
                            std::cout << "!ERROR!: [[" << strFilePath.c_str() << "]]\n";
                            return ::GetLastError();
                        }
                    }

                    ++num_dirs;
                } else {

                    // Set file attributes
                    if( ! ::SetFileAttributes(strFilePath.c_str(),FILE_ATTRIBUTE_NORMAL) ) {
                        std::cout << "!ERROR!: [[" << strFilePath.c_str() << "]]\n";
                        return ::GetLastError();
                    }

                    // Delete file
                    if ( ! ::DeleteFile(strFilePath.c_str()) ) {
                        std::cout << "!ERROR!: [[" << strFilePath.c_str() << "]]\n";
                        return ::GetLastError();
                    }

                    size_files.ull       += FileInformation.nFileSizeLow;
                    size_files.uint.high += FileInformation.nFileSizeHigh;

                    ++num_files;
                }
            }
        } while( ::FindNextFile(hFile,&FileInformation) );

        // Close handle
        ::FindClose( hFile  );
    }

    return 0;
}

unsigned long long num_files_total=0;
unsigned long long num_dirs_total=0;
unsigned long long total_size_files=0;

void my_del_directory( char* dir_name ) {
    int iRC = DeleteDirectory( dir_name );
    //int iRC=0;

    std::cout << "\"" << dir_name << "\""
             "\n    Folders: " << num_dirs
          << "\n    Files:   " << num_files
          << "\n    Size:    " << size_files.ull << " Bytes";
    if(iRC)
    {
        std::cout << "\n!ERROR!: " << iRC;
    }
    std::cout << "\n\n";

    num_dirs_total   += num_dirs;
    num_files_total  += num_files;
    total_size_files += size_files.ull;
    num_dirs  = 1;
    num_files = 0;
    size_files.ull = 0ULL;
    return;
}

int main( void )
{
    size_files.ull = 0ULL;

    my_del_directory( (char*)"C:\Windows\temp"      );
        // This will clear out the System temporary directory on windows systems

    std::cout << "\n\nResults" << "\nTotal Folders: " << num_dirs_total
                   << "\nTotal Files:   " << num_files_total
                   << "\nTotal Size:    " << total_size_files << " Bytes\n";

    return 0;
}
于 2016-09-19T00:27:34.953 回答
-1

如果您使用的是 Windows,请查看此链接。否则,您可能会寻找您的操作系统特定版本的 api。我不认为 C++ 带有跨平台的方式来做到这一点。最后,这不是 C++ 的工作,而是操作系统的工作。

于 2009-04-09T15:35:21.733 回答