【问题标题】:How to remove a non-empty directory in C++?如何在 C++ 中删除非空目录?
【发布时间】:2010-07-19 20:01:10
【问题描述】:

在 C++ 中,如何删除包含所有文件的目录?我知道有rmdir,但它只会删除非空目录,那么如何首先列出并删除所有包含的文件?

我知道使用 Boost Filesystem 应该不难,但我有点想避免构建并依赖它来完成这一项小任务......

【问题讨论】:

  • 这是用于什么平台的? rmdir 向我推荐 Unix 或 Linux。
  • @David:是的,我忘了说我在 Linux 上。 (但 rmdir 是独立于平台的?)但看起来也许使用 Boost 会更好......
  • 如果你真的想用 C++ 进行文件操作,请使用 boost。如果 shell 命令足够,请使用rm -rf [dirname]
  • @dehmann:不完全是“platform-indendent”,而是“常用”(即 Unix/Linux 和 DOS,也许还有其他——Mac OSX 有命令行界面吗?)
  • @James:是的——默认值曾经是 tcsh,但几年前它改为 Bash。大多数其他常见的嫌疑人也可以找到。

标签: c++ file file-io


【解决方案1】:

是的,您通常必须先删除内容。如果您不想为此使用 Boost,那么您几乎只能编写不可移植的代码来查找所有文件(例如,FindFirstFileFindNextFile on Windows、opendirreaddir on Unix 和类似的)递归,并删除所有这些。

在 Windows 上,您还可以使用 ShFileOperationIFileOperation interface。它们可以在内部处理递归删除,因此您只需为其指定要删除的目录的名称,其余部分由它处理。

与大多数 COM 事物一样,IFileOperation 接口似乎专门设计为尽可能笨拙(例如,IFileOperation::DeleteItem 实际上并没有删除任何内容——它只是将一个项目添加到要被删除。然后您必须致电IFileOperation::PerformOperations 进行实际删除。

【讨论】:

    【解决方案2】:

    您可以使用以下代码删除非空目录。这使用 Unix 风格的命令,但可以使用 Cygwin 为 Windows 编译(如果你不介意依赖 Cygwin DLL)。

    void delete_folder_tree (const char* directory_name) {
        DIR*            dp;
        struct dirent*  ep;
        char            p_buf[512] = {0};
    
        dp = opendir(directory_name);
    
        while ((ep = readdir(dp)) != NULL) {
            sprintf(p_buf, "%s/%s", directory_name, ep->d_name);
            if (path_is_directory(p_buf))
                delete_folder_tree(p_buf);
            else
                unlink(p_buf);
        }
    
        closedir(dp);
        rmdir(directory_name);
    }
    
    int path_is_directory (const char* path) {
        struct stat s_buf;
    
        if (stat(path, &s_buf))
            return 0;
    
        return S_ISDIR(s_buf.st_mode);
    }
    

    【讨论】:

    • 请使用这个:“if (strcmp(ep->d_name, ".") == 0 || strcmp(ep->d_name, "..") == 0) continue;"否则你会得到无限循环。 (自我目录)
    【解决方案3】:

    首先,任何文件 i/o(尤其是目录更改)都非常依赖于操作系统。

    但是,在大多数情况下,它是 a) 删除文件,然后 b) 删除目录。 (任何快捷方式都肯定取决于操作系统,并且通常取决于操作系统版本)

    【讨论】:

      【解决方案4】:

      您需要遍历目录中的所有文件并首先删除它们。代码依赖于平台(正如其他人提到的那样)。

      例如,MSDN page 上的代码(从中提取它,因此会有未定义的变量)适用于 Windows,但不适用于 Unix/Linux:

      HANDLE hFind = FindFirstFile(szDir, &ffd);
      
      if (INVALID_HANDLE_VALUE == hFind) 
      {
          DisplayErrorBox(TEXT("FindFirstFile"));
          return dwError;
      } 
      
      // List all the files in the directory with some info about them.
      do
      {
          if (ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
          {
              _tprintf(TEXT("  %s   <DIR>\n"), ffd.cFileName);
          }
          else
          {
              filesize.LowPart = ffd.nFileSizeLow;
              filesize.HighPart = ffd.nFileSizeHigh;
              _tprintf(TEXT("  %s   %ld bytes\n"), ffd.cFileName, filesize.QuadPart);
          }
      }
      while (FindNextFile(hFind, &ffd) != 0);
      
      dwError = GetLastError();
      if (dwError != ERROR_NO_MORE_FILES) 
      {
          DisplayErrorBox(TEXT("FindFirstFile"));
      }
      
      FindClose(hFind);
      

      打印文件信息,但调整它以删除应该不会太难。

      您需要为树中的所有子目录递归地调用它。

      【讨论】:

        猜你喜欢
        • 2010-12-11
        • 2013-08-05
        • 2012-05-31
        • 2016-10-16
        • 2011-01-16
        • 1970-01-01
        • 2010-12-06
        • 1970-01-01
        相关资源
        最近更新 更多