复制目录树

时间:2018-04-06 00:29:18

标签: c c99

由于某些原因,当我运行此代码时,文件未正确地从源目录复制到目标目录。语法为:./a.out source destination。非常感谢任何帮助!

该实用程序用于复制目录树。它将以src-dir为根的整个树复制到以dest-dir为根的目标目录中。因为它不用于经典意义上的目录同步,所以用于从src-dir复制数据的算法有点不寻常。

两个目录树必须存在。如果src-dir或dest-dir不存在,程序将终止并打印一条指示错误的消息。 存在于dest-dir中且src-dir中不存在的实体保持不变。这意味着它不会破坏dest-dir中的任何东西;它只是通过从src-dir复制它们来添加或替换dest-dir中的项目。

如果遇到src-dir中dest-dir中不存在的项,则将其复制到dest-dir中。这包括文件,目录和子目录。

如果遇到dest-dir中存在的src-dir中的目录(或子目录),它将递归到该目录以继续复制过程。如果遇到dest-dir中存在的src-dir文件,则默认行为是比较文件的大小,如果文件大小不同,则复制有问题的文件。在此检查期间不执行文件访问或创建时间的比较。如果两个文件的大小不同,这将导致文件从src-dir复制到dest-dir。

/*                                                                                                                     
 * Usage: ddup (-argument) (-argument) (-argument) (-argument) src-dir dest-dir                                        
 * Note: Arguments may or may not be used, but must be entered in the above format.                                    
 */

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <dirent.h>
#include <string.h>
#include <stdbool.h>
#include <sys/stat.h>
#include <sys/types.h>

void copyDir(char *srcPass, char *dstPass);

bool F = false;
bool V = false;
bool b = false;
bool c = false;

int main(int argc, char **argv) {

  int i;
  unsigned char buffer[4096];
  char *srcPath = argv[argc - 2];
  char *dstPath = argv[argc - 1];

  //Scans the input for arguments and marks them as true if they exist                                                 
  for (i = 1; i < argc; i++) {
    if (argv[i][0] == '-') {
      if (argv[i][1] == 'F') {
        F = true;
      }
      else if (argv[i][1] == 'V') {
        V = true;
      }
      else if (argv[i][1] == 'b') {
        b = true;
      }
      else if (argv[i][1] == 'c') {
        c = true;
      }
    }
  }

  if (V == true) {
    printf("Source Directory: %s\nDestination Directory: %s\n", srcPath, dstPath);
  }

  copyDir(srcPath, dstPath);
}

void copyDir(char *srcPass, char *dstPass) {
  DIR *src = opendir(srcPass);
  DIR *dst = opendir(dstPass);

  struct dirent *dir;
  struct stat buff;

  if (V == true) {
    printf("Contents of the Directory: \n");
  }

  if (src && dst) { //Checks if the src and dst directories exist                                                      

  while ((dir = readdir(src)) != NULL) {

    char ch;
    char newDst[128];

    if (V == true) {
      printf("%s\n", dir->d_name);
    }

    stat(dir->d_name, &buff);
    if(S_ISREG(buff.st_mode)) {

      FILE *fPtr1, *fPtr2;

      //Open the first file for reading                                                                                
      fPtr1 = fopen(dir->d_name, "r");
      if (fPtr1 == NULL) {
        if (V == true) {
          printf("Cannot Open File to Read: %s\n", dir->d_name);
        }
        exit(0);
      }
      else {
        if (V == true) {
          printf("Successfully Opened File to Read: %s\n", dir->d_name);
        }
      }

      //Open the second file for writing                                                                               
      strcpy(newDst, dstPass);
      strcat(newDst, "/");
      strcat(newDst, dir->d_name);
      printf("%s", newDst);
      fPtr2 = fopen(newDst, "w");
      if (fPtr2 == NULL) {
        if (V == true) {
          printf("Cannot Open File to Write: %s\n", dir->d_name);
        }
        exit(0);
      }
      else {
        if (V == true) {
          printf("Successfully Open File to Write: %s\n", dir->d_name);
        }
      }

      //Read contents from the file
      ch = fgetc(fPtr1);
      while (ch != EOF) {
        fputc(ch, fPtr2);
        ch = fgetc(fPtr1);
      }

      if (V == true) {
        printf("The file was successfully coppied!");
      }

      fclose(fPtr1);
      fclose(fPtr2);
    }
  }

  closedir(src);
  closedir(dst);
  }
  else {
    printf("Error: Either the source directory or the destination directory do not exist.\n");

    return;
  }
}

2 个答案:

答案 0 :(得分:1)

您的代码中存在许多问题。以下是主要问题:

  • 使用stat(dir->d_name, &buff);统计源文件这仅在srcPass是当前目录时才有效。您应该在尝试stat并打开它之前构造源文件的名称,最好是通过分配新的字符串来避免路径长度问题。另请注意,您必须检查stat的返回值:如果文件不存在,则stat缓冲区的内容无意义。

  • 您将流中的字节读入char变量ch。您必须将其设为int变量,以便正确检测文件结束条件。

  • 您应该为全局变量提供更明确的名称。具有单个字符名称的全局变量(如c)非常容易混淆且容易出错。

  • 在测试传递的参数数量之前,先从argv[argc - 2]argv[argc - 1]初始化源路径和目标路径。在没有命令行参数的情况下调用您的程序将访问具有未定义行为的argv[-1]

答案 1 :(得分:0)

main()函数可以简化为:

int main(int argc, char **argv)
{
    if( argc == 3 )
    {
        printf("Source: %s, Destination: %s\n", argv[1], argv[2]);
        copyDir( argv[1], argv[2] );
    }

    else
    {
        fprintf( stderr, "USAGE: %s <srcPath> <destPath>\n", argv[0] );
    }

    return 0;
}

但是,代码应该在开始将一个目录的内容复制到另一个目录之前检查两个目录是否存在。

如果目标目录不存在,需要调用(在linux中)mkdir()以确保目标目录实际存在 `