web-dev-qa-db-ja.com

フォルダ内のすべてのファイルを削除するが、NIX標準ライブラリを使用してフォルダを削除しない方法

/ tmpフォルダーの内容を削除するプログラムを作成しようとしています。LinuxでC/C++を使用しています。

_system("exec rm -r /tmp")
_

フォルダー内のすべてを削除しますが、フォルダーも削除します。

system();を介して呼び出される、ある種のbashスクリプトによってこれを行う方法はありますか?または、C/C++でこれを行う直接的な方法はありますか?

私の質問はこれに似ていますが、OS Xではありません... フォルダ内ではなく、フォルダ内のすべてのファイルを削除する方法?

C/C++では、次のことができます。

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

Bashでは、次のことができます。

rm -r /tmp/*

これにより、/ tmp内のすべてが削除されますが、/ tmp自体は削除されません。

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;
}
_

system()またはそのようなものを介して新しいシェルを生成したくない-それは非常に単純なことを行うための多大なオーバーヘッドであり、システムで利用可能なものについて不必要な仮定(および依存関係)を行います。

47
Demitri

ワイルドカード_*_文字を使用することにより、任意のタイプの拡張子を持つすべてのファイルを削除できます。

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

3
eqzx

できるよ

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

C/C++では、以下を使用できます(隠しディレクトリを含む):

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

しかし、「rm」または「find」ユーティリティがshに利用できない場合はどうすればよいでしょうか?「ftw」と「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;
}
2
cmllamas

これは非常に古い質問であることがわかっていますが、Demitriの素晴らしい答えに基づいて、必要に応じてサブフォルダ内のファイルを再帰的に削除する関数を作成しました

someエラー処理も行い、errnoを返します。関数ヘッダーは、doxygenによる解析用に記述されています。この関数は、私が使用した単純な例の場合に機能し、隠しフォルダーと隠しファイルを削除します。

これが将来誰かに役立つことを願っています

#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

nftw(3) を使用できます。最初に、削除するファイルパスのセットを収集するパスを作成します。次に、2番目のパスでunlink(ディレクトリ以外の場合)および rmdir(2) を使用します