Как сравнить несколько файлов только по типу и размеру файла - PullRequest
0 голосов
/ 06 февраля 2019

Цель - сравнить файлы по размеру и отфильтровать файлы одинакового размера.Для этого вам нужно сравнить каждый файл с каждым файлом.Однако первый цикл не работает, поэтому поиск первого каталога застрял в первом файле.

#include <dirent.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <sys/stat.h>

int main(int argc, char *v[]) {
    struct dirent *d_verzeichnis1;
    struct dirent *d_verzeichnis2;
    DIR *dir1;
    DIR *dir2;
    FILE *file = fopen(v[3], "W");
    dir1 = opendir(v[1]);
    dir2 = opendir(v[2]);
    struct stat filesize1;
    struct stat filesize2;

    while ((d_verzeichnis1 = readdir(dir1)) != NULL) {
        stat((d_verzeichnis1->d_name), &filesize1);
        while ((d_verzeichnis2 = readdir(dir2)) != NULL) {
            stat((d_verzeichnis2->d_name), &filesize2);
            if (filesize1.st_size == filesize2.st_size);
            {
                printf("%s und %s sind gleich\n", 
                       d_verzeichnis1->d_name, d_verzeichnis2->d_name);
            }
        }   
        d_verzeichnis1 = readdir(dir1); 
    }
}

1 Ответ

0 голосов
/ 06 февраля 2019

В вашем коде есть несколько проблем:

  • Вы должны проверить фактическое количество аргументов, предоставленных в командной строке, чтобы избежать неопределенного поведения, если было предоставлено менее 3.
  • fopen(v[3], "W"); использует недопустимую строку режима, вы должны использовать "w".Непонятно, для чего этот указатель потока используется в любом случае.
  • dir1 и dir2 не тестируются: у вас неопределенное поведение при сбое opendir(). Вызывается
  • statс именем записи каталога, которое не является относительным путем к файлу, если каталог отличается от текущего каталога.Вы должны составить имя пути из имени каталога и имени записи.
  • if (filesize1.st_size == filesize2.st_size); имеет дополнительный ; в конце строки, в результате чего следующий блок выполняется безоговорочно.Вы должны использовать K&R style with {`в конце строки, чтобы избежать таких глупых ошибок.
  • логика параллельного сканирования неверна: вы должны заново открыть или, по крайней мере, перемотать второй каталог для каждой записи в первомдля полного сканирования возможных совпадений.

Вот исправленная версия:

#include <dirent.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <sys/stat.h>

char *buildpath(char *dest, size_t size, const char *dir, const char *name) {
    size_t len = strlen(dir);
    const char *sep = "";

    if (len > 0 && dir[len - 1] != '/')
        sep = "/";

    if ((unsigned)snprintf(dest, size, "%s%s%s", dir, sep, name) < size)
        return dest;
    else
        return NULL;
}

int main(int argc, char *argv[]) {
    char path1[1024];
    char path2[1024];
    struct dirent *dp1;
    struct dirent *dp2;
    DIR *dir1;
    DIR *dir2;
    struct stat filesize1;
    struct stat filesize2;

    if (argc < 3) {
        fprintf(stderr, "missing argument\n");
        fprintf(stderr, "usage: cmpdir dir1 dir2\n");
        return 1;
    }

    dir1 = opendir(argv[1]);
    if (dir1 == NULL) {
        fprintf(stderr, "cannt open directory %s: %s\n", argv[1], strerror(errno));
        return 1;
    }
    dir2 = opendir(argv[2]);
    if (dir2 == NULL) {
        fprintf(stderr, "cannt open directory %s: %s\n", argv[2], strerror(errno));
        return 1;
    }
    while ((dp1 = readdir(dir1)) != NULL) {
        /* ignore . and .. entries */
        if (!strcmp(dp1->d_name, ".")
        ||  !strcmp(dp1->d_name, ".."))
            continue;
        if (!buildpath(path1, sizeof path1, argv[1], dp1->d_name)) {
            /* path too long */
            continue;
        }
        if (stat(path1, &filesize1)) {
            /* cannot stat entry */
            continue;
        }
        if (!S_ISREG(filesize1.st_mode)) {
            /* not a regular file */
            continue;
        }
        rewinddir(dir2);
        while ((dp2 = readdir(dir2)) != NULL) {
            /* ignore . and .. entries */
            if (!strcmp(dp2->d_name, ".")
            ||  !strcmp(dp2->d_name, ".."))
                continue;
            if (!buildpath(path2, sizeof path2, argv[2], dp2->d_name)) {
                /* path too long */
                continue;
            }
            if (stat(path2, &filesize2)) {
                /* cannot stat entry */
                continue;
            }
            if (!S_ISREG(filesize2.st_mode)) {
                /* not a regular file */
                continue;
            }
            if (filesize1.st_size == filesize2.st_size) {
                printf("%s and %s have the same size %llu\n",
                       path1, path2, (unsigned long long)filesize1.st_size);
                /* perform actual comparison... */
            }
        }
    }
    closedir(dir1);
    closedir(dir2);
    return 0;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...