How can I delete a folder using C++?
If no cross-platform way exists, then how to do it for the most-popular OSes - Windows, Linux, Mac, iOS, Android? Would a POSIX solution work for all of them?
How can I delete a folder using C++?
If no cross-platform way exists, then how to do it for the most-popular OSes - Windows, Linux, Mac, iOS, Android? Would a POSIX solution work for all of them?
With C++17 you can use std::filesystem
, in C++14 std::experimental::filesystem
is already available. Both allow the usage of 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");
Note 1:
Those functions throw filesystem_error in case of errors. If you want to avoid catching exceptions, use the overloaded variants with std::error_code
as second parameter. E.g.
std::error_code errorCode;
if (!std::filesystem::remove("myEmptyDirectoryOrFile", errorCode)) {
std::cout << errorCode.message() << std::endl;
}
Note 2:
The conversion to std::filesystem::path
happens implicit from different encodings, so you can pass strings to filesystem::remove()
.
I strongly advise to use Boost.FileSystem.
http://www.boost.org/doc/libs/1_38_0/libs/filesystem/doc/index.htm
In your case that would be
Delete folder (sub_folders and files) in Windows (VisualC++) not using Shell APIs, this is the best working sample:
#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;
}
Source: http://www.codeguru.com/forum/showthread.php?t=239271
The directory should be empty.
BOOL RemoveDirectory( LPCTSTR lpPathName );
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);
}
path
ends with a '/' then only the /content/ should be deleted and the - now empty - directory itself should remain; also if(*(entry->d_name) != '.')
should check for "." and "..", the way it is currently it will not delete hidden files. otherwise this is cool. –
King Use SHFileOperation to remove the folder recursivelly
The directory must be empty and your program must have permissions to delete it
but the function called rmdir will do it
rmdir("C:/Documents and Settings/user/Desktop/itsme")
#include <direct.h>
I believe, same as _mkdir –
Lisettelisha You can also try this if you are on linux:
system("rm -r path");
[C++ 17]
In order to delete a directory and all the contents of directory (its subdirectories recursively) and in the end delete directory itself use remove_all from standard library.
std::filesystem::remove_all(directory);
This works for deleting all the directories and files within a directory.
#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;
}
The C++ Standard defines the remove() function, which may or may not delete a folder, depending on implementation. If it doesn't you need to use an implementation specific function such as rmdir().
I do not have the "reputation" to comment, so I have to make an answer.
As far as I could see the previous solution for Windows contains an error (in checking the ".": it does not delete directories like .ssh for example).
Furthermore, the (now necessary) management of UTF-8 paths is missing.
// 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;
}
Now I put a UNIX/Linux version, based on fixed previous functions
#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;
}
//For windows:
#include <direct.h>
if(_rmdir("FILEPATHHERE") != -1)
{
//success
} else {
//failure
}
My own implementation based off hB0 that also allows you to view the number of files in each folder also with a little performance boost.
#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;
}
DeleteDirectory
? You declare it for real two lines lower. –
Swanner For linux (I have fixed bugs in code above):
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);
}
For 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);
}
}
If you are using the Poco library, here is a portable way to delete a directory.
#include "Poco/File.h"
...
...
Poco::File fooDir("/path/to/your/dir");
fooDir.remove(true);
The remove function when called with "true" means recursively delete all files and sub directories in a directory.
If you are using windows, then take a look at this link. Otherwise, you may look for your OS specific version api. I don't think C++ comes with a cross-platform way to do it. At the end, it's NOT C++'s work, it's the OS's work.
Try use system "rmdir -s -q file_to_delte
".
This will delete the folder and all files in it.
-s
flag there. On windows, this attempts to remove the -s
and -q
directories. –
Paragrapher © 2022 - 2024 — McMap. All rights reserved.