【发布时间】:2019-01-08 16:55:42
【问题描述】:
我的程序需要检测给定文件中的重复项并用硬链接替换它们。它在 Windows 上工作正常(没有链接),但它在 linux 上不起作用。 对于文件夹中的 5 个文件,结果是: List & Results。它可以正确检测 Windows 上的重复项,但那些 NULL 可能会在 linux 上阻止它。我尝试添加如果在 listFiles 末尾(不活动 //)它是一个很好的列表,但没有检测到 windows 上的第二个重复项(未在 linux 上测试)。顺便说一句,我在底部提到了斜线,但要注意。 谢谢帮忙。
#include <stdio.h>
#include <string.h>
#include <dirent.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
int compare(char *file_1, char *file_2);
int listFiles(char *path, int *count, char ***list);
int hardlink (char *path_1, char *path_2);
int is_regular_file(const char *path);
int main()
{
char path[100];
int count=0;
int comp=0;
char **list=NULL;
printf("input path: ");
scanf("%s", path);
count=listFiles(path,&count,&list);
printf("%d\n",count);
if(list==NULL){
printf("wrong path");
return 1;
}
for(int i=0;i<count;++i)
{
printf("%d %s\n",i,list[i]);
}
for (int i=0; i<count; ++i){
for (int j=i+1; j<count; ++j){
comp= compare(list[i], list[j]);
if(comp==0&&list[j]!=NULL&&list[i]!=NULL){
printf("%s to dup %s\n",list[j],list[i]);
// hardlink (list[i], list[j]);
for(int k=j ;k<count-1;++k){
list[k]=list[k+1];
}
free(list[count]);
--count;
}
}
}
for (int i = 0; i < count; ++i)
free(list[i]);
free(list);
return 0;
}
int listFiles(char *basePath,int *count, char ***list)
{
char path[1000];
int temp=*count;
struct dirent *dp;
DIR *dir = opendir(basePath);
if (!dir){
return temp;
}
while ((dp = readdir(dir)) != NULL){
if (strcmp(dp->d_name, ".") != 0 && strcmp(dp->d_name, "..") != 0){
strcpy(path, basePath);
strcat(path, "/");
strcat(path, dp->d_name);
char *file_path=NULL;
if (is_regular_file(path)){
int x=0;
for( int i =0;path[i]!='\0';++i){
file_path=realloc(file_path, (x+1)*sizeof(*file_path));
(file_path)[x++] = path[i];
}
file_path=realloc(file_path, (x+1)*sizeof(*file_path));
file_path[x]='\0';
}
// if(file_path!=NULL){
*list=realloc(*list, (temp+1)*sizeof(**list));
(*list)[temp++] = file_path;
// }
}
temp=listFiles(path,&temp,list);
}
closedir(dir);
return temp;
}
int compare(char *file_1, char *file_2)
{
FILE *data_1 = fopen(file_1,"r");
FILE *data_2 = fopen(file_2,"r");
char *temp_1=malloc(10000);
char *temp_2=malloc(10000);
if (data_1){
int x=0;
int c;
while ((c = fgetc(data_1)) != EOF){
(temp_1)[x++] = (char) c;
}
temp_1[x] = '\0';
}
if (data_2){
int x=0;
int c;
while ((c = fgetc(data_2)) != EOF){
(temp_2)[x++] = (char) c;
}
temp_2[x] = '\0';
}
fclose(data_1);
fclose(data_2);
if(strcmp(temp_1,temp_2)==0)return 0;
else return 1;
}
int hardlink (char *path_1, char *path_2){
int temp= remove(path_2);
if (temp==0)printf("file %s deleted\n", path_2);
else {
printf("can't delete %s\n", path_2);
return 1;
}
int linking = link ( path_1 , path_2 ) ;
if (linking == 0){
FILE *fil = fopen (path_2, "r");
if (fil != NULL){
printf (" hardlink %s for %s created\n",path_2,path_1);
fclose(fil);
}
else printf("can't create hardlink %s\n", path_2);
return 0;
}
else printf("can't create hardlink %s\n", path_2);
puts("");
return 0;
}
int is_regular_file(const char *path)
{
struct stat path_stat;
stat(path, &path_stat);
return S_ISREG(path_stat.st_mode);
}
在列表文件中你需要改变 strcat(path, "\");到 strcat(路径,“/”);如果你想在 linux 上工作
【问题讨论】:
-
strcat(path, "\\");可能是您的问题。 unix 中的路径分隔符是 '/' -
if(comp==0&&list[j]!=NULL&&list[i]!=NULL)- 不要节省空间... -
您似乎在问题的最后给出了答案。那你到底想知道什么?
-
您在 compare 中有几个问题:2 个大内存泄漏,2 个 malloc 没有空闲,并且您的比较不适用于大于 10000 的文件。但最后你不需要根本要记住两个文件的所有内容来比较它们,只需逐块读取它们(不是逐字符)并比较读取的块,当读取大小不同或它们的内容不同时停止。这样做你没有内存泄漏,也没有要比较的文件大小问题,这更快
-
我怀疑
strcat(path, "/");可以在两个操作系统中工作。
标签: c