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

查看:21
本文介绍了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
 ", 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
", 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
", 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.

一旦它在文件夹中找不到更多的目录(它已经到达叶"文件夹),它将遍历剩余的文件,然后结束函数,从堆栈中弹出最后一个函数调用,允许前一个函数调用调用 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.

P.S:抱歉剧透,我是在打完字后才阅读您的评论.

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

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

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