[완료:C source] 파일이 존재하는 디렉토리 지우기

ahsan의 이미지

검색기로 파일이 존재하는 디렉토리 지우는 함수를 찾아 보았는데 없더군요
Linux에서 remove, rmdir은 파일이 존재하는 directory를 못지우니
어쩔 수 없이 만들어 보았는데 뭔가 좀 어정쩡하다는 느낌입니다.
실행하면 돌아가기는 하는데 return 처리가 문제입니다.
작업이 순조롭게 끝나면 1이 리턴되고 그렇지 않으면 -1이 리턴되게 해야 하는데 어떻게 해야할지를 모르겠습니다.

고수님들의 수정을 부탁드립니다.

int delDirFile(const char* folder)
{
   DIR* dp;
   struct dirent *dirp;
   struct stat file_stat;
   char targetfile[512];
 
 
   if((dp = opendir(folder)) == NULL)
   {
      perror("Open Error : ");
      return -1;
   }
   printf("Target Directory open Succeed!\n");
 
   while(1)
   {
      if(!(dirp = readdir(dp)))
      {
         perror("readdir Error : ");
         closedir(dp);
         remove(folder);
         return -1;
      }
 
      sprintf(targetfile, "%s/%s", folder, dirp->d_name);   // Path와 파일이름을 합친다
      stat(targetfile, &file_stat);
 
      if((file_stat.st_mode & S_IFMT) == S_IFDIR)        // Directory 이면...
      {
         continue;
      }
      if(remove(targetfile) == 0)
      {
         continue;
      }
      else
      {
         perror("remove Error : ");
         break;
      }
   }
   return 1;
}
blueiur의 이미지

rm -rf folder_name

planetarium의 이미지

이런 답변은 없느니만 못합니다.
track comments 보니 이런 답변이 한둘이 아니시네요.

blueiur의 이미지

검색기로 파일이 존재하는 디렉토리 지우는 함수를 찾아 보았는데 없더군요
Linux에서 remove, rmdir은 파일이 존재하는 directory를 못지우니
어쩔 수 없이 만들어 보았는데 뭔가 좀 어정쩡하다는 느낌입니다.

파일이 존재하는 디렉토리를 못지워서 "어쩔 수 없이" 만드셨다고 하시잖아요.

planetarium의 이미지

질문의 도메인이 쉘이 아니라 C입니다.
man 1 rmdir 에 나오는 rmdir 이 아니라
man 2 rmdir 에 나오는 rmdir() 이라는 거죠.

C 안에서 함수 하나로 처리했으면 좋겠는데
그게 안돼서 코드를 작성하고 싶다는 질문입니다.
왜 제가 질문을 설명하고 있는지는 모르겠지만...

blueiur의 이미지


제가 부주의하게 잘못 읽었네요.
앞으로 주의하겠습니다.

ahsan의 이미지

님의 수고 덕분에 C를 배우는 많은 사람들이 큰 도움을 얻을 것입니다.

오늘의 경우와는 다르지만 ....
예전에 저는 모기잡는 전등(TV에서 아이디어 상품으로 출연)을 구입해서 사용해 보니
모기잡는 것과 전혀 관계없는 그냥 조명등이라는 사실을 알았습니다.
그냥 속은 샘 치고 잊을려 했지만 한편으론 다른 피해자들이 생길 것 같아서
글을 올렸다가 한동안 판매자와 시비를 벌인적이 있었습니다.

옥션과 판매자와 재조사에서 전화가 오는 것이 힘들었지만
요즘 하도 사기가 많아서 내가 당하는 정도에서
잘못된 상품을 구매하는 것을 못하게 하는 것이 모두를 위해 도움이 될 것 같아서
성가신 일을 자청한 적이 있었지요.

리눅스 콘솔 명령어에 대한 답변을 올리신 분은 그 분 입장에서 잘못된 것은 없지만
범주를 잘못 살폈으니 잠깐의 착오를 이해해 주시기 바랍니다.
감사합니다.

planetarium의 이미지

지나가다 그저 까칠하게 한마디 한 것 뿐인데
이렇게 정중하게 말씀해 주시니... 당황스럽습니다;
좋은 말씀 감사합니다. 행복하세요.

ahsan의 이미지

리눅스 콘솔 명령어군요.

philnet의 이미지

sub directory를 가지는 directory 일 경우는 재귀 호출을 통해 처리할 수 있을 것 같습니다.

int delDirFile(const char* folder)
{
   /* ... */
   while(1)
   {
      /* ... */
      if ( S_ISDIR(file_stat.st_mode) )        // Directory 이면...
      {
         if ( delDirFile(targetfile) == -1 ) // sub directory 삭제를 위해 자기 자신을 재귀 호출
         {
            return -1; // 실패 시 -1 반환
         }
 
         continue;
      }
 
      if ( unlink(targetfile) == -1 )
      {
         return -1; // 실패 시 -1 반환
      }
 
      continue;
 
      /* ... */
   }
 
   // folder 디렉토리의 모든 항목들 제거후, folder를 제거
   int result = rmdir(folder);
   closedir(dp);
   return result == 0 ? 1; -1;
}

단순한 remove() 함수보다는, regular file 삭제 시에는 unlink(), 빈 디렉토리 삭제 시에는 rmdir()을 호출해 주는 게 좋을 듯 싶습니다.

하지만 readdir() 했을 때, 특수한 디렉토리, 즉 현재 디렉토리를 나타내는 dot(.), 상위 디렉토리를 나타내는 dot-dot(..), lost+found 은 확인해서 skip 해 줘야 문제가 안 되겠지요.

	/* DOTDOT = "..", DOT = ".", LOST_FOUND = "lost+found" */
 
	boolean isToBeSkipped = strcmp(dirp->d_name, DOTDOT) == 0
		|| strcmp(dirp->d_name, DOT) == 0 || strcmp(dirp->d_name, LOST_FOUND) == 0;
	if( isToBeSkipped )
	{
		continue;	
	}

끝으로, 반환 값은, delDirFile() 함수 내에서 사용하는 함수들처럼, 성공하면 0, 그렇지 않으면 에러 코드를 반환하는 방식이 더 좋을 듯 싶습니다.

ahsan의 이미지

명쾌하고 세심한 답변 감사드립니다.

지적해 주신 내용을 보면서
readdir(), remove(), rmdir(), unlink()함수들이 왜 필요하며
어떻게 사용해야 하는지를 분명하게 이해할 수 있었습니다.
또한 파일 검색에도 응용이 될 것같네요.

clique의 이미지

ftw(), nftw()라는 file tree walking(traversing) 함수가 있습니다. SUS에 속해 있죠.

http://www.opengroup.org/onlinepubs/9699919799/

기본적으로는 pre-order traverse입니다만, 옵션을 줘서 post-order로 traverse할 수 있습니다.

#include <ftw.h>
#include <stdio.h>
#include <stdlib.h>
 
static int
rmdir_helper(const char *fpath, const struct stat *sb,
	int tflag, struct FTW *ftwbuf)
{
	switch ( tflag )
	{
		case FTW_D:
		case FTW_DP:
			if ( rmdir(fpath) == -1 )
				perror("unlink");
			break;
 
		case FTW_F:
		case FTW_SL:
			if ( unlink(fpath) == -1 )
				perror("unlink");
			break;
 
        default:
			puts("do nothing");
	}
	return 0;
}
 
int main(int argc, char* argv)
{
	const char* dir_to_remove = "/path/to/remove";
	int flags = 0;
	flags |= FTW_DEPTH; // post-order traverse
 
	if ( argc == 2 )
		dir_to_remove = argv[1];
 
	if (nftw((dir_to_remove, rmdir_helper, 10, flags) == -1)
	{
		perror("nftw");
		exit(EXIT_FAILURE);
	}
	return 0;
}

코드는 이런 방식입니다. (돌려보지는 않았습니다)

ahsan의 이미지

==> nftw()
이런 함수가 있는지는 꿈에도 몰랐네요.
사용방법이 마치 pthread_create 같은 함수처럼 보입니다.
SUS가 정확히 뭔지는 모르지만 GCC라는 것이 생각밖에 풍부한 라이브러리를 가지고 있는듯 합니다.

감사합니다.

clique의 이미지

callback function을 이용한 방법입니다.

SUS는 Single Unix Specification으로(아마), 여러 유닉스 간의 사양쯤 됩니다. POSIX(Portable OS Interface for Unix)와 비슷하죠. 리눅스는 대체로 SUS와 POSIX를 만족합니다.

madman93의 이미지

---------------------------------------------
git init
git add .
git commit -am "project init"
---------------------------------------------
나중에 살펴보면 유용한 코드가 되겠군요
잘 읽었습니다.

---------------------------------------------
git init
git add .
git commit -am "project init"
---------------------------------------------

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.