【问题标题】:Recursive directory copying in CC中的递归目录复制
【发布时间】:2013-02-17 02:43:56
【问题描述】:

我对 C 编程非常陌生,关于如何递归复制 C 中目录的内容(不是 C++、C#、Objective-C、Java、shell、Python 或其他任何东西)的有用信息很少-- 这必须在 C) 中完成。是的,这是家庭作业,明天晚上就要交了,我已经被困了将近两个星期,试图完成这项工作。

我正在尝试搜索给定目录的任何备份版本(例如,带有备份目录“/dir.bak”的目录“dir”)。如果没有,则创建该“/dir.bak”目录,或者如果有,则创建一个名为“/dir.bak.MM-DD-YY-HH-MM-SS”的备份目录。然后将源目录中的所有内容复制到目标目录中。

当我尝试运行这段代码时:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <dirent.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <sys/time.h>
#include <time.h>

#define BUFSIZE 256

int main (int argc, char* argv[])
{
    DIR *dir;
    struct dirent *dentry;
    struct stat statbuff;
    char buffer[BUFSIZE];//holds time and date suffix
    ssize_t count;
    int fdin, fdout;    
    mode_t  perms =  740;//perms for file I/O ops
    char *cwdNamePntr;
    long maxpath;
    if ( argc != 3 ) //if incorrect number of args passed in...
    {
        printf( "Usage: %s Directory-Path-Name Destination-Folder\n ", argv[0] );
        exit(1);
    }
    char  buffer2[BUFSIZE];//buffer for file I/O ops
    char* datetime;
    int retval;
    time_t  clocktime;
    struct tm  *timeinfo;
    time (&clocktime);
    timeinfo = localtime( &clocktime );
    strftime(buffer, BUFSIZE, "%b-%d-%Y-%H-%M-%S", timeinfo);//store time and date suffix in case we need it
    chdir(argv[1]);
    char *path = argv[2];//source path for I/O ops
    char *newpath = malloc(strlen(path) + 26);//destination paths for I/O ops
    strcpy(newpath,path);
    strcat(newpath,".bak");//test name for backup directory
    if(chdir(newpath)==0)
    {//if our test name is already a directory
        chdir("..");
        strcat(newpath,".");
        strcat(newpath,buffer);//add time and date suffix onto the name of new backup directory
    }
    if ( (mkdir(newpath, perms)) == 0 )//if we successfully made a new backup directory
    {
        chdir(path);
        dir = opendir(".");//move into source directory
        if ( dir ==  0 )
        {//if open directory fails
                fprintf (stderr, "Error in opening directory:  %s\n", path );
            perror( "Could not open directory");
                exit(2);
        }
        dentry = readdir (dir);//load directory

        while (dentry != 0)//while we are reading a directory
        {
            char *filename = dentry->d_name;//get name of file to be copied
            if( (strcmp(filename,".")!=0) && (strcmp(filename,"..")!=0) )
            {
                if  ( (fdin = open ( filename,  O_RDONLY))  == -1)
                {//if cannot open input file
                        perror ( "Error in opening the input file:");
                        exit (2);
                }
                chdir("..");//go back to parent directory
                chdir(newpath);//move to destination directory
                opendir(".");
                if  ( (fdout = open (filename, (O_WRONLY | O_CREAT), perms)) == -1 )
                {//if cannot create output file...
                        perror ( "Error in creating the output file:");
                        exit (3);
                }
                while ( (count=read(fdin, buffer2, BUFSIZE)) > 0 )
                {
                        if ( write (fdout, buffer2, count) != count )
                    {//if cannot write   
                                perror ("Error in writing" );
                                exit(3);
                        }
                } 

                    if ( count == -1 )
                    {//if cannot read
                        perror ( "Error while reading the input file: ");
                        exit(4);
                }

                close(fdin);
                close(fdout);
            }
            chdir("..");//back to parent directory again
            dir = opendir(".");
            if ( dir ==  0 )//if open directory fails
            {
                    fprintf (stderr, "Error in opening directory:  %s\n", path );
                perror( "Could not open directory");
                    exit(666);
            }
            dentry = readdir (dir);//reload directory
        }
    }
    else
    {
        perror("Error in directory creation");
        exit(2);
    }
    return 0;  
}

我收到此错误:

[my-desktop]@ubuntu:~/Desktop$ ./helpmehelpyou.out ~/Desktop new
Error in creating the output file:: Permission denied

这些代码的一部分取自我们的讲师说我们可以使用的示例文件。我不明白为什么这不起作用?完成的函数必须是递归的,并且是选项 4 的四选择程序的一部分。C 对我来说很难掌握或理解,就像我说的,关于 C 的这些东西的信息很少,但是对于 C#、C++、Objective C 和所有其他语言来说,它的数量过多。就像我也说过的,我们不能使用 shell 命令或其他任何东西来完成这项任务。

有人可以帮我吗?谢谢!

【问题讨论】:

  • 您要求我们查看的代码非常多。我建议您至少自己进行一些调试,以找到 when 在您的程序执行过程中发生此错误。一旦你知道了,你可能应该在它周围构造​​一个minimal test-case
  • 你有创建文件的权限吗?
  • 这对我来说似乎不是很“递归”。您是否不必为每个路径和子路径调用“搜索此目录”函数才能使其工作?
  • @millerseke:一个特定的提示是:添加打印语句everywhere(或使用调试器)以跟踪程序的活动。这将帮助您确定何时发生错误。
  • 我们正在努力帮助您,真的。只是它的代码很多,而且我们这里没有调试器来查看是哪一行实际导致了问题。现在,你检查过它应该去的目录实际上被创建了吗?

标签: c recursion tree directory copy


【解决方案1】:

这不能解决您的问题,但我发现您的代码中可能存在错误。我没有看到递归发生。

您知道,如果您只有一个子文件夹,此代码可能会正常工作。但是,如果该子文件夹中有子文件夹,您会怎么做?

您需要递归目录搜索功能。 这可能看起来像这样:

void SearchDirectory(const char *name) {
    DIR *dir = opendir(name);                //Assuming absolute pathname here.
    if(dir) {
        char Path[256], *EndPtr = Path;
        struct dirent *e;
        strcpy(Path, name);                  //Copies the current path to the 'Path' variable.
        EndPtr += strlen(name);              //Moves the EndPtr to the ending position.
        while((e = readdir(dir)) != NULL) {  //Iterates through the entire directory.
            struct stat info;                //Helps us know about stuff
            strcpy(EndPtr, e->d_name);       //Copies the current filename to the end of the path, overwriting it with each loop.
            if(!stat(Path, &info)) {         //stat returns zero on success.
                if(S_ISDIR(info.st_mode)) {  //Are we dealing with a directory?
                    //Make corresponding directory in the target folder here.
                    SearchDirectory(Path);   //Calls this function AGAIN, this time with the sub-name.
                } else if(S_ISREG(info.st_mode) { //Or did we find a regular file?
                    //Run Copy routine
                }
            }
        }
    }
}

此代码将调用函数SearchDirectory 的次数与当前文件夹中的子目录相同。如果架构运行太深,可能会耗尽内存,导致程序崩溃,请注意。

一旦在文件夹中找不到更多目录(它已到达“叶”文件夹),它将遍历剩余的文件,然后结束函数,从堆栈中弹出最后一个函数调用,允许前一个拨打SearchDirectory继续搜索。

说到底,你会得到一个完整的递归副本。

P.S:抱歉剧透,我是在打字后才看到你的评论。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-05-18
    • 2013-11-06
    • 2011-06-22
    • 2016-07-28
    • 2013-08-17
    • 1970-01-01
    • 2016-04-18
    • 2013-07-01
    相关资源
    最近更新 更多