递归目录复制C [英] Recursive directory copying in C

查看:332
本文介绍了递归目录复制C的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我是C编程的新手,并且没有什么有用的信息在任何地方如何递归复制目录的内容在C(不是C ++,C#,Objective-C,Java,shell,Python或任何其他 - 这必须在C)。是的,这是家庭作业,明天晚上,我已经卡住了将近两个星期试图做到这一点。

I am very new to C programming and there is little helpful information anywhere on how to do recursive copying of the contents of a directory in C (not C++,C#, Objective-C, Java, shell, Python, or anything else--this MUST be done in C). Yes, this is homework and it is due tomorrow night, and I have been stuck for almost two weeks trying to get this done.

我试图搜索任何备份给定目录的版本(例如,具有备份目录/dir.bak的目录dir)。如果没有,则创建/dir.bak目录,如果存在,则创建一个名为/dir.bak.MM-DD-YY-HH-MM-SS的备份目录。

I am trying to search for any backup versions of a given directory (e.g. a directory "dir" with a backup directory "/dir.bak"). If there is not, create that "/dir.bak" directory, or if there is, create a backup directory named "/dir.bak.MM-DD-YY-HH-MM-SS" instead. Then copy everything from the source directory into the destination directory.

当我尝试运行此代码时:

When I attempt to run this code:

#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命令或任何其他的任务。

A bunch of this code was taken from sample files which our instructors said we could use. I don't understand why this is not working right? The finished function must be recursive and is part of a four-choice program with this being option 4. C is very hard for me to grasp or understand, and like I said, there is very little information about this stuff for C, but an overabundance of it for C#, C++, Objective C, and every other language. And like I also said, we MAY NOT use shell commands or anything else for this assignment.

有人可以帮助我吗?谢谢!

Can someone please help me? Thanks!

推荐答案

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

This won't solve your problem, but I spotted a possible error in your code. I don't see the recursion happening.

你看,如果你只有一个子文件夹,这个代码可能会正常工作。但是,如果该子文件夹中有子文件夹,您该怎么办?

You see, this code may work fine if you only have one subfolder. But what do you do, if there's a subfolder in that subfolder?

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

You need a recursive directory search function. This may look like this:

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 的次数与当前文件夹中的子目录的次数相同。如果体系结构运行得太深,可能会用完内存,程序可能会崩溃,请小心。

This code will call the function SearchDirectory for as many times as there are subdirectories in the current folder. If the architecture runs too deep you may run out of memory and the program may crash, so please beware.

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

Once it cannot find any more directories in the folder (it has reached the 'leaf'-folders), it will iterate over the remaining files and then end the function, popping the last function call from the stack, allowing the previous call to SearchDirectory to continue searching.

完成所有操作后,有完整的递归副本。

After all is said and done, you'll have a full recursive copy.

PS:对不起,扰乱,我只有在我完成输入后阅读您的评论。

P.S: Sorry for the spoiler, I read your comment only after I was done typing.

这篇关于递归目录复制C的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆