如何使用C ++删除文件夹?
如果不存在跨平台方式,那么如何为最流行的操作系统 - Windows,Linux,Mac,iOS,Android? POSIX解决方案是否适用于所有这些解决方案?
答案 0 :(得分:58)
答案 1 :(得分:20)
在Windows(VisualC ++)中删除不使用Shell API的文件夹(子文件夹和文件),这是最好的工作示例:
#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;
}
答案 2 :(得分:13)
使用C ++ 17,您可以使用std::filesystem
,在C ++ 14中std::experimental::filesystem
已经可用。两者都允许使用filesystem::remove()
。
C ++ 17:
#include <filesystem>
std::filesystem::path::remove("myEmptyDirectoryOrFile"); // Deletes empty directories or single files.
std::filesystem::path::remove_all("myDirectory"); // Deletes one or more files recursively.
C ++ 14:
#include <experimental/filesystem>
std::experimental::filesystem::path::remove("myDirectory");
注1:
如果出现错误,这些函数会抛出filesystem_error。如果要避免捕获异常,请使用带有std::error_code
的重载变量作为第二个参数。 E.g。
std::error_code errorCode;
if (!std::filesystem::path::remove("myEmptyDirectoryOrFile", errorCode)) {
std::cout << errorCode.message() << std::endl;
}
注2:
从std::filesystem::path
隐式转换为filesystem::remove()
,因此您可以将字符串传递给normalize vs denormalize。
答案 3 :(得分:9)
目录应为空。
BOOL RemoveDirectory( LPCTSTR lpPathName );
答案 4 :(得分:6)
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);
}
答案 5 :(得分:5)
使用SHFileOperation递归删除文件夹
答案 6 :(得分:4)
目录必须为空,并且您的程序必须具有删除它的权限
但是名为rmdir的函数会这样做
rmdir("C:/Documents and Settings/user/Desktop/itsme")
答案 7 :(得分:3)
如果您使用的话,也可以试试这个:
system("rm -r path");
答案 8 :(得分:1)
这适用于删除目录中的所有目录和文件。
{{1}}
答案 9 :(得分: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;
}
答案 10 :(得分:0)
C ++标准定义了remove()函数,该函数可能会也可能不会删除文件夹,具体取决于实现。如果不是,则需要使用特定于实现的函数,例如rmdir()。
答案 11 :(得分:0)
尝试使用系统“rmdir -s -q file_to_delte
”。
这将删除文件夹及其中的所有文件。
答案 12 :(得分:0)
//对于Windows:
#include <direct.h>
if(_rmdir("FILEPATHHERE") != -1)
{
//success
} else {
//failure
}
答案 13 :(得分: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;
}
答案 14 :(得分: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);
}
对于Windows:
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);
}
}
答案 15 :(得分:0)
如果您使用的是Poco库,这是一种删除目录的简便方法。
#include "Poco/File.h"
...
...
Poco::File fooDir("/path/to/your/dir");
fooDir.remove(true);
以“ true”调用时,remove函数意味着递归删除目录中的所有文件和子目录。
答案 16 :(得分:-2)
如果您使用的是Windows,请查看this link。否则,您可能会查找特定于操作系统的版本API。我不认为C ++有跨平台的方式来实现它。最后,这不是C ++的工作,而是操作系统的工作。