在C或C ++中以编程方式删除非空目录

如何删除C或C ++中的非空目录? 有没有什么function? rmdir只删除空目录。 请提供一种不使用任何外部库的方式。

另外告诉我如何删除C或C ++文件?

你想写一个函数(recursion函数是最简单的,但是可以很容易地在深度目录中运行堆栈空间),它将枚举一个目录的子目录。 如果你发现一个孩子是一个目录,你就这个问题recursion。 否则,你删除里面的文件。 完成后,目录是空的,您可以通过系统调用删除它。

要枚举Unix上的目录,可以使用opendirreaddirclosedir 。 要删除你在一个空目录(即在你的函数的末尾,在删除子项之后rmdir()使用rmdir() ,并在文件上unlink() 。 请注意,在许多系统上, struct direntd_type成员不受支持; 在这些平台上,您将不得不使用stat()S_ISDIR(stat.st_mode)来确定给定path是否为目录。

在Windows上,您将使用FindFirstFile() / FindNextFile()枚举空目录上的DeleteFile()DeleteFile()以删除文件。

下面是一个可以在Unix上运行的例子(完全未经testing):

 int remove_directory(const char *path) { DIR *d = opendir(path); size_t path_len = strlen(path); int r = -1; if (d) { struct dirent *p; r = 0; while (!r && (p=readdir(d))) { int r2 = -1; char *buf; size_t len; /* Skip the names "." and ".." as we don't want to recurse on them. */ if (!strcmp(p->d_name, ".") || !strcmp(p->d_name, "..")) { continue; } len = path_len + strlen(p->d_name) + 2; buf = malloc(len); if (buf) { struct stat statbuf; snprintf(buf, len, "%s/%s", path, p->d_name); if (!stat(buf, &statbuf)) { if (S_ISDIR(statbuf.st_mode)) { r2 = remove_directory(buf); } else { r2 = unlink(buf); } } free(buf); } r = r2; } closedir(d); } if (!r) { r = rmdir(path); } return r; } 

最简单的方法是使用Boost.Filesystem库的remove_all函数。 此外,生成的代码将是可移植的。

如果你想写一些特定于Unix(rmdir)或Windows(RemoveDirectory)的东西,那么你将不得不编写一个函数,以recursion方式删除子文件和子文件夹。

编辑

看起来这个问题已经被问到 ,实际上有人已经推荐了Boost的remove_all。 所以请不要高兴我的答案。

许多类Unix系统(Linux,BSD和OS X,至less)都具有用于目录遍历的ftsfunction。 要recursion删除目录,只需执行深度优先遍历(不符合链接),并删除每个访问的文件。

 int recursive_delete(const char *dir) { int ret = 0; FTS *ftsp = NULL; FTSENT *curr; // Cast needed (in C) because fts_open() takes a "char * const *", instead // of a "const char * const *", which is only allowed in C++. fts_open() // does not modify the argument. char *files[] = { (char *) dir, NULL }; // FTS_NOCHDIR - Avoid changing cwd, which could cause unexpected behavior // in multithreaded programs // FTS_PHYSICAL - Don't follow symlinks. Prevents deletion of files outside // of the specified directory // FTS_XDEV - Don't cross filesystem boundaries ftsp = fts_open(files, FTS_NOCHDIR | FTS_PHYSICAL | FTS_XDEV, NULL); if (!ftsp) { fprintf(stderr, "%s: fts_open failed: %s\n", dir, strerror(errno)); ret = -1; goto finish; } while ((curr = fts_read(ftsp))) { switch (curr->fts_info) { case FTS_NS: case FTS_DNR: case FTS_ERR: fprintf(stderr, "%s: fts_read error: %s\n", curr->fts_accpath, strerror(curr->fts_errno)); break; case FTS_DC: case FTS_DOT: case FTS_NSOK: // Not reached unless FTS_LOGICAL, FTS_SEEDOT, or FTS_NOSTAT were // passed to fts_open() break; case FTS_D: // Do nothing. Need depth-first search, so directories are deleted // in FTS_DP break; case FTS_DP: case FTS_F: case FTS_SL: case FTS_SLNONE: case FTS_DEFAULT: if (remove(curr->fts_accpath) < 0) { fprintf(stderr, "%s: Failed to remove: %s\n", curr->fts_path, strerror(errno)); ret = -1; } break; } } finish: if (ftsp) { fts_close(ftsp); } return ret; } 

如果您使用的是POSIX兼容的操作系统,则可以使用nftw()进行文件树遍历并删除(删除文件或目录)。 如果你使用C ++,并且你的项目使用boost,那么使用Manuelbuild议的Boost.Filesystem并不是一个坏主意。

在下面的代码示例中,我决定不遍历符号链接和挂载点(只是为了避免大的删除:)):

 #include <stdio.h> #include <stdlib.h> #include <ftw.h> static int rmFiles(const char *pathname, const struct stat *sbuf, int type, struct FTW *ftwb) { if(remove(pathname) < 0) { perror("ERROR: remove"); return -1; } } int main(int argc, char *argv[]) { if (argc != 2) { fprintf(stderr,"usage: %s path\n",argv[0]); exit(1); } // Delete the directory and its contents by traversing the tree in reverse order, without crossing mount boundaries and symbolic links if (nftw(argv[1], rmFiles,10, FTW_DEPTH|FTW_MOUNT|FTW_PHYS) < 0) { perror("ERROR: ntfw"); exit(1); } return 0; } 

您可以使用opendirreaddir来读取目录条目并取消链接来删除它们。

 //====================================================== // Recursely Delete files using: // Gnome-Glib & C++11 //====================================================== #include <iostream> #include <string> #include <glib.h> #include <glib/gstdio.h> using namespace std; int DirDelete(const string& path) { const gchar* p; GError* gerr; GDir* d; int r; string ps; string path_i; cout << "open:" << path << "\n"; d = g_dir_open(path.c_str(), 0, &gerr); r = -1; if (d) { r = 0; while (!r && (p=g_dir_read_name(d))) { ps = string{p}; if (ps == "." || ps == "..") { continue; } path_i = path + string{"/"} + p; if (g_file_test(path_i.c_str(), G_FILE_TEST_IS_DIR) != 0) { cout << "recurse:" << path_i << "\n"; r = DirDelete(path_i); } else { cout << "unlink:" << path_i << "\n"; r = g_unlink(path_i.c_str()); } } g_dir_close(d); } if (r == 0) { r = g_rmdir(path.c_str()); cout << "rmdir:" << path << "\n"; } return r; } 

unlink将删除一个文件。

remove也将删除一个文件,但更便携。

如果你在Linux上工作,你可能会尝试system("rm -r ./path") ,否则还有一个Windows APIrecursion删除function。