programing

C 또는 C++에서 비어 있지 않은 디렉토리를 프로그래밍 방식으로 제거

sourcetip 2022. 8. 8. 23:01
반응형

C 또는 C++에서 비어 있지 않은 디렉토리를 프로그래밍 방식으로 제거

C 또는 C++에서 비어 있지 않은 디렉토리를 삭제하려면 어떻게 해야 합니까?어떤 기능이 있나요?rmdir는 빈 디렉토리만 삭제합니다.외부 라이브러리를 사용하지 않는 방법을 제공해 주세요.

C 또는 C++에서 파일을 삭제하는 방법도 알려주세요.

POSIX 준거 OS 를 사용하고 있는 경우는, 파일 트리 트래버설 및 삭제(파일 또는 디렉토리 삭제)에 사용할 수 있습니다.C++에 있고 프로젝트에서 부스트를 사용하는 경우 부스트를 사용하는 것도 나쁘지 않습니다.Manuel이 제안한 파일 시스템.

다음 코드 예에서는 심볼릭링크와 마운트포인트를 통과하지 않기로 결정했습니다(대략적인 삭제를 피하기 위해서만).

#include <stdio.h>
#include <stdlib.h>
#include <ftw.h>

static int rmFiles(const char *pathname, const struct stat *sbuf, int type, struct FTW *ftwb)
{
    if(remove(pathname) < 0)
    {
        perror("ERROR: remove");
        return -1;
    }
    return 0;
}

int main(int argc, char *argv[])
{
    if (argc != 2)
    {
        fprintf(stderr,"usage: %s path\n",argv[0]);
        exit(1);
    }

    // Delete the directory and its contents by traversing the tree in reverse order, without crossing mount boundaries and symbolic links

    if (nftw(argv[1], rmFiles,10, FTW_DEPTH|FTW_MOUNT|FTW_PHYS) < 0)
    {
        perror("ERROR: ntfw");
        exit(1);
    }

    return 0;
}

★★★unix- 시스템 라이크 시스템(- 라이크 시스템(- 라이크 시스템)Linux , . . . . . . . .BSD §OS X는 '적어도'를 있다.fts이치노

디렉토리를 반복적으로 삭제하려면 깊이 우선 트래버설(다음 심볼링크 없음)을 수행하여 방문한 모든 파일을 삭제합니다.

int recursive_delete(const char *dir)
{
    int ret = 0;
    FTS *ftsp = NULL;
    FTSENT *curr;

    // Cast needed (in C) because fts_open() takes a "char * const *", instead
    // of a "const char * const *", which is only allowed in C++. fts_open()
    // does not modify the argument.
    char *files[] = { (char *) dir, NULL };

    // FTS_NOCHDIR  - Avoid changing cwd, which could cause unexpected behavior
    //                in multithreaded programs
    // FTS_PHYSICAL - Don't follow symlinks. Prevents deletion of files outside
    //                of the specified directory
    // FTS_XDEV     - Don't cross filesystem boundaries
    ftsp = fts_open(files, FTS_NOCHDIR | FTS_PHYSICAL | FTS_XDEV, NULL);
    if (!ftsp) {
        fprintf(stderr, "%s: fts_open failed: %s\n", dir, strerror(errno));
        ret = -1;
        goto finish;
    }

    while ((curr = fts_read(ftsp))) {
        switch (curr->fts_info) {
        case FTS_NS:
        case FTS_DNR:
        case FTS_ERR:
            fprintf(stderr, "%s: fts_read error: %s\n",
                    curr->fts_accpath, strerror(curr->fts_errno));
            break;

        case FTS_DC:
        case FTS_DOT:
        case FTS_NSOK:
            // Not reached unless FTS_LOGICAL, FTS_SEEDOT, or FTS_NOSTAT were
            // passed to fts_open()
            break;

        case FTS_D:
            // Do nothing. Need depth-first search, so directories are deleted
            // in FTS_DP
            break;

        case FTS_DP:
        case FTS_F:
        case FTS_SL:
        case FTS_SLNONE:
        case FTS_DEFAULT:
            if (remove(curr->fts_accpath) < 0) {
                fprintf(stderr, "%s: Failed to remove: %s\n",
                        curr->fts_path, strerror(curr->fts_errno));
                ret = -1;
            }
            break;
        }
    }

finish:
    if (ftsp) {
        fts_close(ftsp);
    }

    return ret;
}

디렉토리의 자식을 열거하는 함수(재귀 함수가 가장 쉬우나 딥 디렉토리의 스택 공간이 쉽게 부족해질 수 있음)를 작성하려고 합니다.디렉토리인 하위 항목이 발견되면 해당 항목이 반복됩니다.그렇지 않으면 안에 있는 파일을 삭제합니다.작업이 완료되면 디렉토리가 비어 있으므로 syscall을 통해 삭제할 수 있습니다.

의 하려면 , 를 합니다.opendir(),readdir() , , , , 입니다.closedir()하려면 , 를 사용합니다rmdir() 기능 후) 및 """ (자녀 삭제 후)"" 。unlink()파일에 저장해당.에서 " " "는d_type in의 struct dirent에서는, 「」를 사용할 .이러한 플랫폼에서는stat() ★★★★★★★★★★★★★★★★★」S_ISDIR(stat.st_mode)지정된 경로가 디렉토리인지 확인합니다.

에서는, 의 「」를 사용합니다.FindFirstFile()/FindNextFile()RemoveDirectory() 및 「」, 「」에 DeleteFile()파일을 삭제합니다.

다음은 Unix(완전히 테스트되지 않음)에서 작동하는 예입니다.

int remove_directory(const char *path) {
   DIR *d = opendir(path);
   size_t path_len = strlen(path);
   int r = -1;

   if (d) {
      struct dirent *p;

      r = 0;
      while (!r && (p=readdir(d))) {
          int r2 = -1;
          char *buf;
          size_t len;

          /* Skip the names "." and ".." as we don't want to recurse on them. */
          if (!strcmp(p->d_name, ".") || !strcmp(p->d_name, ".."))
             continue;

          len = path_len + strlen(p->d_name) + 2; 
          buf = malloc(len);

          if (buf) {
             struct stat statbuf;

             snprintf(buf, len, "%s/%s", path, p->d_name);
             if (!stat(buf, &statbuf)) {
                if (S_ISDIR(statbuf.st_mode))
                   r2 = remove_directory(buf);
                else
                   r2 = unlink(buf);
             }
             free(buf);
          }
          r = r2;
      }
      closedir(d);
   }

   if (!r)
      r = rmdir(path);

   return r;
}

에는 C++17'이 있습니다.<experimental\filesystem>부스트 버전을 기반으로 합니다.

std::experimental::filesystem::remove_all을 사용하여 재귀적으로 삭제합니다.

제어가 더 필요한 경우 std::experimental::filesystem::recursive_directory_iterator를 사용해 보십시오.

또한 반복기의 비재귀 버전을 사용하여 사용자 고유의 재귀를 쓸 수도 있습니다.

namespace fs = std::experimental::filesystem;
void IterateRecursively(fs::path path)
{
  if (fs::is_directory(path))
  {
    for (auto & child : fs::directory_iterator(path))
      IterateRecursively(child.path());
  }

  std::cout << path << std::endl;
}

가장 쉬운 방법은 Boost의 remove_all 기능을 사용하는 것입니다.파일 시스템 라이브러리게다가 결과 코드는 휴대할 수 있게 됩니다.

Unix(rmdir) 또는 Windows(RemoveDirectory) 전용으로 쓰려면 하위 파일과 하위 폴더를 반복적으로 삭제하는 함수를 작성해야 합니다.

편집

이 질문은 이미 한 것 같습니다.실제로 누군가가 이미 Boost의 remove_all을 추천했습니다.그러니 제발 내 대답을 무시하지 말아줘.

opendirreaddir를 사용하여 디렉토리 엔트리를 읽고 링크를 해제하여 삭제할 수 있습니다.

//======================================================
// Recursely Delete files using:
//   Gnome-Glib & C++11
//======================================================

#include <iostream>
#include <string>
#include <glib.h>
#include <glib/gstdio.h>

using namespace std;

int DirDelete(const string& path)
{
   const gchar*    p;
   GError*   gerr;
   GDir*     d;
   int       r;
   string    ps;
   string    path_i;
   cout << "open:" << path << "\n";
   d        = g_dir_open(path.c_str(), 0, &gerr);
   r        = -1;

   if (d) {
      r = 0;

      while (!r && (p=g_dir_read_name(d))) {
          ps = string{p};
          if (ps == "." || ps == "..") {
            continue;
          }

          path_i = path + string{"/"} + p;


          if (g_file_test(path_i.c_str(), G_FILE_TEST_IS_DIR) != 0) {
            cout << "recurse:" << path_i << "\n";
            r = DirDelete(path_i);
          }
          else {
            cout << "unlink:" << path_i << "\n";
            r = g_unlink(path_i.c_str());
          }
      }

      g_dir_close(d);
   }

   if (r == 0) {
      r = g_rmdir(path.c_str());
     cout << "rmdir:" << path << "\n";

   }

   return r;
}

c의 unlinkat()를 사용하여 비어있지 않은 폴더를 삭제하려면 어떻게 해야 합니까?

다음은 제 연구 결과입니다.

    /*
     * Program to erase the files/subfolders in a directory given as an input
     */

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <dirent.h>
    #include <unistd.h>
    #include <sys/types.h>
    #include <sys/stat.h>
    #include <fcntl.h>
    void remove_dir_content(const char *path)
    {
        struct dirent *de;
        char fname[300];
        DIR *dr = opendir(path);
        if(dr == NULL)
        {
            printf("No file or directory found\n");
            return;
        }
        while((de = readdir(dr)) != NULL)
        {
            int ret = -1;
            struct stat statbuf;
            sprintf(fname,"%s/%s",path,de->d_name);
            if (!strcmp(de->d_name, ".") || !strcmp(de->d_name, ".."))
                        continue;
            if(!stat(fname, &statbuf))
            {
                if(S_ISDIR(statbuf.st_mode))
                {
                    printf("Is dir: %s\n",fname);
                    printf("Err: %d\n",ret = unlinkat(dirfd(dr),fname,AT_REMOVEDIR));
                    if(ret != 0)
                    {
                        remove_dir_content(fname);
                        printf("Err: %d\n",ret = unlinkat(dirfd(dr),fname,AT_REMOVEDIR));
                    }
                }
                else
                {
                    printf("Is file: %s\n",fname);
                    printf("Err: %d\n",unlink(fname));
                }
            }
        }
        closedir(dr);
    }
    void main()
    {
        char str[10],str1[20] = "../",fname[300]; // Use str,str1 as your directory path where it's files & subfolders will be deleted.
        printf("Enter the dirctory name: ");
        scanf("%s",str);
        strcat(str1,str);
        printf("str1: %s\n",str1);
        remove_dir_content(str1); //str1 indicates the directory path
    }

언급URL : https://stackoverflow.com/questions/2256945/removing-a-non-empty-directory-programmatically-in-c-or-c

반응형