我是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命令或其他任何东西进行这项任务。
有人可以帮帮我吗?谢谢!
答案 0 :(得分:2)
这不会解决您的问题,但我发现代码中可能存在错误。我没有看到递归发生。
你知道,如果你只有一个子文件夹,这段代码可能会正常工作。但是如果该子文件夹中有子文件夹,你会怎么做?
您需要一个递归目录搜索功能。 这可能如下所示:
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
的次数与当前文件夹中的子目录一样多。如果架构运行得太深,可能会耗尽内存,程序可能会崩溃,所以请注意。
一旦它找不到文件夹中的任何目录(它已到达'leaf'-folders),它将遍历剩余的文件,然后结束该函数,从堆栈弹出最后一个函数调用,允许以前的致电SearchDirectory
继续搜索。
毕竟说完了,你将有一个完整的递归副本。
P.S:对于剧透,我只是在打字后才读到您的评论。