递归删除目录

时间:2012-12-09 21:35:56

标签: c unix

我已多次尝试编写一个函数来删除目录和目录中的文件,例如rm -r,但我没有设法做到这一点。我尝试过的技术是:

/* rm command */
#include <fts.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/types.h>

#define DEBUG

int rm_file(const char **argv);
int rm_tree(const char **argv);
void usage(void);

int rflag = 0;

int main(int argc, char *argv[])
{
    int ch;

    while((ch = getopt(argc, argv, "Rr")) != -1) {
        switch(ch) {
            case 'R':
            case 'r':
                rflag = 1;
                break;
            default:
                usage();
        }
    }
    argc -= optind;
    argv += optind;

    while(*argv) {
        if(rflag)
            rm_tree(argv);
        else
            rm_file(argv);
        argv++;
    }

    return 0;
}

int rm_tree(const char **argv)
{
    FTS *ftsp;
    FTSENT *ftsent;

    if((ftsp = fts_open(argv, 0, NULL)) == NULL) {
        fprintf(stderr, "error: rm: can't stat directory\n");
        return 1;
    }

    while((ftsent = fts_read(ftsp)) != NULL) {
        switch(ftsent->fts_info) {
            case FTS_DNR:
                fprintf(stderr, "error: rm: can't stat directory\n");
                break;
#ifndef DEBUG
            case FTS_D:
                rm_tree(&ftsent->fts_accpath);
                break;
#endif
            case FTS_F:
                if(unlink(ftsent->fts_accpath) == -1) {
                    fprintf(stderr, "error: rm: can't remove file\n");
                }
                break;
            case FTS_SL:
                if(unlink(ftsent->fts_accpath) == -1) {
                    fprintf(stderr, "error: rm: can't remove file\n");
                }
                break;
            default:
                if(unlink(ftsent->fts_accpath) == -1) {
                    fprintf(stderr, "error: rm: can't remove file\n");
                }
                break;
        }
    }

    if(rmdir(*argv) == -1) {
        fprintf(stderr, "error: rm: can't remove directory\n");
        return 1;
    }

    return 0;
}

int rm_file(const char **argv)
{
    struct stat st;

    if(lstat(*argv, &st) == -1) {
        fprintf(stderr, "error: rm: can't stat file\n");
        return 1;
    }

    if(S_ISDIR(st.st_mode)) {
        fprintf(stderr, "error: rm: can't remove directory\n");
        return 1;
    }

    if(unlink(*argv) == -1) {
        fprintf(stderr, "error: rm: can't remove file\n");
        return 1;
    }

    return 0;
}

void usage(void) 
{
    fprintf(stderr, "usage: rm file1 file2\n");
    exit(1);
}

但总是会出现分段错误,或者它无法正常工作。我正朝着正确的方向前进吗?我已经尝试使用ftw()函数和opendir()函数,但我还是无法弄清楚如何使其工作。如果有人可以提供帮助,我将不胜感激。

调试标记中包含的代码是失败的原因。

1 个答案:

答案 0 :(得分:4)

通过分析开源操作系统中rm的源代码,看看它在实践中是如何完成的,例如: OpenBSD(寻找rm_tree)。