web-dev-qa-db-fra.com

Comment supprimer tous les fichiers d'un dossier sans supprimer le dossier à l'aide des bibliothèques standard NIX?

J'essaie de créer un programme qui supprime le contenu du dossier/tmp. J'utilise C/C++ sur Linux.

system("exec rm -r /tmp")

supprime tout dans le dossier mais supprime aussi le dossier que je ne veux pas.

Est-il possible de faire cela avec une sorte de script bash, appelé via system(); ou y a-t-il un moyen direct de le faire en C/C++?

Ma question est similaire à celle-ci, mais je ne suis pas sous OS X ... comment supprimer tous les fichiers d’un dossier, mais pas le dossier lui-même?

En C/C++, vous pourriez faire:

system("exec rm -r /tmp/*")

Dans Bash, vous pourriez faire:

rm -r /tmp/*

Cela supprimera tout ce qui se trouve dans/tmp, mais pas/tmp lui-même.

15
Jay Sullivan
#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;
}

Vous ne voulez pas créer un nouveau Shell via system() ou quelque chose du genre - cela prend beaucoup de temps pour faire quelque chose de très simple et cela crée des hypothèses inutiles (et des dépendances) sur ce qui est disponible sur le système.

44
Demitri

en utilisant le caractère générique *, vous pouvez supprimer tous les fichiers avec n'importe quel type d'extension.

system("exec rm -r /tmp/*")

3
eqzx

tu peux faire

system("exec find /tmp -mindepth 1 -exec rm {} ';'");
3
ALiX

En C/C++, vous pouvez utiliser (y compris les répertoires cachés):

system("rm -r /tmp/* /tmp/.*");
system("find /tmp -mindepth 1 -delete");

Mais que se passe-t-il si les utilitaires 'rm' ou 'find' ne sont pas disponibles pour sh ?, mieux vaut utiliser 'ftw' et '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;
}
1
cmllamas

Je réalise que c'est une question très ancienne, mais en me basant sur l'excellente réponse de Demitri, j'ai créé une fonction qui supprimera récursivement les fichiers des sous-dossiers si vous le souhaitez.

Il gère également les erreurs some en ce sens qu'il renvoie errno errno. L'en-tête de la fonction est écrit pour être analysé par doxygen. Cette fonction fonctionne dans les cas simples que j'ai utilisés et supprime les dossiers et fichiers cachés.

J'espère que cela aidera quelqu'un d'autre à l'avenir

#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;
}
1
andrew

Vous pouvez utiliser nftw (3) . Tout d’abord, faites une passe pour collecter l’ensemble des chemins de fichiers à supprimer. Ensuite, utilisez unlink (pour les non-répertoires) et rmdir (2) dans un second passage

0