Thread: Comparing Directories

  1. #1
    Registered User
    Join Date
    Dec 2011
    Posts
    4

    Comparing Directories

    This is a C program that's being written with a Linux shell. The goal is to compare two different directories and report what is NEW, MODIFIED, or DELETED.

    I'm stuck on the figuring out whether a file exists in the base directory but not the modified directory, in which case the file name should be printed to the screen along with the message DELETED.

    I've already figured out the NEW and MODIFIED for the most part. Sub directories aren't supposed to be printed out but I can't resolve that either.

    Can anyone help point me in the right direction? Here's the code I have so far.

    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include <dirent.h>
    #include <sys/stat.h>
    #include <string.h>
    
    
    int main(int argc, char ** argv)
    {
    
        int recurse = 0;    
        int diff = 0;        
        char * basedir = NULL;
        char * moddir = NULL;    
    
        int i;
        for (i = 1; i < argc; i++)
        {
            if (argv[i][0] == '-')
            {
                if (strcmp(argv[i], "-R") == 0)
                {
                    recurse = 1;
                }
                else if (strcmp(argv[i], "-D") == 0)
                {
                    diff = 1;
                }
                else
                {
                    printf("error: invalid option %s\n", argv[i]);
                    exit(-1);
                }
            }
            else
            {
                if (basedir == NULL)
                {
                    basedir = argv[i];
                }
                else if (moddir == NULL)
                {
                    moddir = argv[i];
                }
                else
                {
                    printf("error: invalid argument %s\n", argv[i]);
                    exit(-2);
                }
            }
        }
    
        if ((basedir == NULL) || (moddir == NULL))
        {
            printf("error: must pass both basedir and moddir\n");
            exit(-3);
        }
    
        DIR * moddir_contents = opendir(moddir);
        if (moddir_contents != NULL)
        {
            struct dirent * moddir_entry = readdir(moddir_contents);
            while (moddir_entry != NULL)
            {
    
                DIR * basedir_contents = opendir(basedir);
                if (basedir_contents != NULL)
                {
                    int matched = 0;    
                    int deleted = 0;
    
                    struct dirent * basedir_entry = readdir(basedir_contents);
                    while (basedir_entry != NULL)
                    {
    
                        if (strcmp((*moddir_entry).d_name, (*basedir_entry).d_name) == 0)
                        {
                            matched = 1;
    
            
                            struct stat buf;
    
                            time_t mod_stamp;
                            char modfilename[1024];
                            strcpy(modfilename, moddir);
                            strcat(modfilename, "/");
                            strcat(modfilename, (*moddir_entry).d_name);
                            if (stat(modfilename, &buf) == 0)
                            {
                                mod_stamp = buf.st_mtime;
                            }
                            else
                            {
                                printf("error: failed to get modified time for file %s\n", (*moddir_entry).d_name);
                
                                exit(-5);
                            }
    
                            time_t base_stamp;
                            char basefilename[1024];
                            strcpy(basefilename, basedir);
                            strcat(basefilename, "/");
                            strcat(basefilename, (*basedir_entry).d_name);
                            if (stat(basefilename, &buf) == 0)
                            {
                                base_stamp = buf.st_mtime;
                            }
                            else
                            {
                                printf("error: failed to get modified time for file %s\n", (*basedir_entry).d_name);
                                exit(-5);
                            }
    
                            if (mod_stamp > base_stamp)
                            {
                                printf("%s MODIFIED!\n", (*moddir_entry).d_name);
                            }
                        }
    
                        basedir_entry = readdir(basedir_contents);
                    }
    
                    if (matched == 0)
                    {
                        printf("%s NEW\n", (*moddir_entry).d_name);
                    }
    
                    closedir(basedir_contents);
                }
                else
                {
                    printf("error: failed to open basedir %s\n", basedir);
        
                    exit(-5);
                }
    
                moddir_entry = readdir(moddir_contents);
            }
    
            closedir(moddir_contents);
        }
        else
        {
            printf("error: failed to open moddir %s\n", moddir);
            exit(-4);
        }
    
        return 0;
    }

  2. #2
    Registered User
    Join Date
    Nov 2010
    Location
    Long Beach, CA
    Posts
    5,909
    Since this is Linux, don't use negative exit values or return values from main. In Linux, the exit code gets cast to an unsigned char, so only values 0-255 are valid. If you run your program in such a way that makes it exit with code -3, then you echo that code with echo $? ($? is the special shell variable that holds the exit value of the last command) you will not see -3.

    The DELETED case is the same as the NEW case, except the inner and outer loops are switched.

  3. #3
    Registered User
    Join Date
    Dec 2011
    Posts
    4
    Is there a concise way to do that? Or is it inevitably going to be messy?

  4. #4
    Registered User
    Join Date
    Nov 2010
    Location
    Long Beach, CA
    Posts
    5,909
    Concise way to do what? Fix your exit codes or write your DELETED case? Neither one will be "messy", though adding the DELETED case will require more than one or two lines of code.

  5. #5
    Registered User
    Join Date
    Dec 2011
    Posts
    4
    Ah ok. I got that part working, thanks. Somehow there's suppose to be a recursive way to display even the files in the sub directories. This has me really stumped. Any suggestions ?

  6. #6
    Registered User
    Join Date
    Nov 2010
    Location
    Long Beach, CA
    Posts
    5,909
    Well, you need to start by not having everything in main. You need a function that does the actual comparison and tells you what is new/modified/deleted. Let main just handle the option parsing then call the comparison function with a flag to tell you whether to recurse. If that flag is true, recurse at the appropriate time, passing in the new directories to compare. There are a couple "appropriate" times, depending on how you want the output to turn out. I'll let you figure that part out.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. build tree of directories sub-directories using linked-lists
    By geekoftheweek in forum C Programming
    Replies: 3
    Last Post: 10-02-2008, 11:13 PM
  2. Comparing 2 directories
    By Opel_Corsa in forum C++ Programming
    Replies: 4
    Last Post: 01-19-2007, 11:30 PM
  3. VC6 directories
    By Magos in forum Tech Board
    Replies: 0
    Last Post: 03-11-2005, 05:52 PM
  4. Directories
    By calpol2004 in forum Windows Programming
    Replies: 1
    Last Post: 10-26-2004, 03:09 PM
  5. directories
    By Shakespeare in forum C++ Programming
    Replies: 4
    Last Post: 03-15-2002, 01:02 PM