I am trying to create a program that deletes the contents of the /tmp folder, I am using C/C++ on linux.
system("exec rm -r /tmp")
deletes everything in the folder but it deletes the folder too which I dont want.
Is there any way to do this by some sort of bash script, called via system()
; or is there a direct way i can do this in C/C++?
My question is similar to this one, but im not on OS X... how to delete all files in a folder, but not the folder itself?
In C/C++, you could do:
system("exec rm -r /tmp/*")
In Bash, you could do:
rm -r /tmp/*
This will delete everything inside /tmp, but not /tmp itself.
#include <stdio.h>
#include <dirent.h>
int main()
{
// These are data types defined in the "dirent" header
DIR *theFolder = opendir("path/of/folder");
struct dirent *next_file;
char filepath[256];
while ( (next_file = readdir(theFolder)) != NULL )
{
// build the path for each file in the folder
sprintf(filepath, "%s/%s", "path/of/folder", next_file->d_name);
remove(filepath);
}
closedir(theFolder);
return 0;
}
You don't want to spawn a new shell via system()
or something like that - that's a lot of overhead to do something very simple and it makes unnecessary assumptions (and dependencies) about what's available on the system.
you can do
system("exec find /tmp -mindepth 1 -exec rm {} ';'");
by using use the wildcard *
character you can delete all the files with any type of extension.
system("exec rm -r /tmp/*")
In C/C++ you can use (including hidden directories):
system("rm -r /tmp/* /tmp/.*");
system("find /tmp -mindepth 1 -delete");
But what if 'rm' or 'find' utilities are not availabe to sh?, better go 'ftw' and 'remove':
#define _XOPEN_SOURCE 500
#include <ftw.h>
static int remove_cb(const char *fpath, const struct stat *sb, int typeFlag, struct FTW *ftwbuf)
{
if (ftwbuf->level)
remove(fpath);
return 0;
}
int main(void)
{
nftw("./dir", remove_cb, 10, FTW_DEPTH);
return 0;
}
I realize this is very old question, but building on Demitri's great answer I created a function that will recursively delete files in subfolders if desired
It also does some error handling, in that it passes back errno. The function header is written for parsing by doxygen. This function works in the simple example cases I used, and deletes hidden folders and hidden files.
I hope this helps someone else in the future
#include <stdio.h>
#include <dirent.h>
#include <sys/stat.h>
#define SUCCESS_STAT 0
/**
* checks if a specific directory exists
* @param dir_path the path to check
* @return if the path exists
*/
bool dirExists(std::string dir_path)
{
struct stat sb;
if (stat(dir_path.c_str(), &sb) == 0 && S_ISDIR(sb.st_mode))
return true;
else
return false;
}
/**
* deletes all the files in a folder (but not the folder itself). optionally
* this can traverse subfolders and delete all contents when recursive is true
* @param dirpath the directory to delete the contents of (can be full or
* relative path)
* @param recursive true = delete all files/folders in all subfolders
* false = delete only files in toplevel dir
* @return SUCCESS_STAT on success
* errno on failure, values can be from unlink or rmdir
* @note this does NOT delete the named directory, only its contents
*/
int DeleteFilesInDirectory(std::string dirpath, bool recursive)
{
if (dirpath.empty())
return SUCCESS_STAT;
DIR *theFolder = opendir(dirpath.c_str());
struct dirent *next_file;
char filepath[1024];
int ret_val;
if (theFolder == NULL)
return errno;
while ( (next_file = readdir(theFolder)) != NULL )
{
// build the path for each file in the folder
sprintf(filepath, "%s/%s", dirpath.c_str(), next_file->d_name);
//we don't want to process the pointer to "this" or "parent" directory
if ((strcmp(next_file->d_name,"..") == 0) ||
(strcmp(next_file->d_name,"." ) == 0) )
{
continue;
}
//dirExists will check if the "filepath" is a directory
if (dirExists(filepath))
{
if (!recursive)
//if we aren't recursively deleting in subfolders, skip this dir
continue;
ret_val = DeleteFilesInDirectory(filepath, recursive);
if (ret_val != SUCCESS_STAT)
{
closedir(theFolder);
return ret_val;
}
}
ret_val = remove(filepath);
//ENOENT occurs when i folder is empty, or is a dangling link, in
//which case we will say it was a success because the file is gone
if (ret_val != SUCCESS_STAT && ret_val != ENOENT)
{
closedir(theFolder);
return ret_val;
}
}
closedir(theFolder);
return SUCCESS_STAT;
}
You could use nftw(3). First, make a pass to collect the set of file paths to remove. Then use unlink
(for non-directories) and rmdir(2) in a second pass