- 平臺:Windows XP服務包3
- 編譯:代碼:: Blocks的版本12.11
我目前正在寫一個程序,將遞歸刪除給定的目錄使用POSIX目錄功能。但是,我對readdir()和它的對應dirent結構有問題。我在readdir的documentation中讀到,對函數的多次調用將覆蓋函數返回的結構中保存的數據。所以我認爲readdir()必須爲結構本身包含內存,然後簡單地將指針地址重新分配給捕獲返回值的結構。我測試了這個理論,並且我是正確的readdir()爲它的成員d_name分配了內存。我遇到的問題是,當目錄流爲空時,readdir返回一個空指針,所以我使用while循環(條件爲dirent_ptr!= NULL)迭代整個目錄。但是因爲readdir()將處理結構的內存分配,我只需聲明一個dirent結構並讓readdir()完成它的工作。由於某種原因,dirent結構被初始化爲NULL(或者它可能是我的編譯器),所以我的循環從不啓動,因爲它的條件語句不是initialy true。所以我想我的問題是我在這裏做錯了什麼?我需要分配內存的結構的dirent
這裏是重要的變量聲明和包含的圖書館。請注意,所有這些變量都是全局聲明的。
#include <stdio.h>
#include <stdlib.h>
#include <dirent.h>
#include <sys/stat.h>
#include <string.h>
int recursive_delete(const char *path);
int file_delete(const char *path, int file_size);
struct dirent *direntp;
struct stat *statp;
struct switches
{
int verbose;
int no_prompt;
int continue_if_error;
int files_only;
}; struct switches switches;
而不是解析相對路徑我簡單地cd到作爲參數給出的路徑,然後使用。和通配符移動導向器,以使相對路徑(d_names)有效。另外開關結構只包含命令行開關,應該被忽略,我知道在下面的代碼中的錯誤,但非常不能修復它們,因爲我無法克服上述問題。
int recursive_delete(const char *path)
{
DIR *dirp;
int return_value = 0;
int recursive_return_value = 0;
if((chdir(path)) == -1)
{
perror("ERROR(3)");
return 1;
}
printf("CDED to \"%s\"\n", path);
dirp = opendir(".");
if(dirp == NULL)
{
perror("ERROR(4)");
return 1;
}
printf("OPENED \"%s\"\n", path);
while(direntp != NULL)
{
direntp = readdir(dirp);
if((direntp == NULL) && (errno != 0))
{
perror("ERROR(5)");
return 1;
}
printf("READ \"%s\" FROM \"%s\"\n", direntp->d_name, path);
if((strcmp(direntp->d_name, ".")!=0) && (strcmp(direntp->d_name, "..")!=0))
{
if((stat(direntp->d_name, statp)) == -1)
{
perror("ERROR(6)");
return 1;
}
printf("STATED \"%s\"\n", direntp->d_name);
if(S_ISREG(statp->st_mode))
{
printf("DELETING \"...\\%s\\%s\"\n", path, direntp->d_name);
return_value += file_delete(direntp->d_name, statp->st_size);
if((!switches.continue_if_error) && (return_value != 0))
{
break;
}
}
else if(S_ISDIR(statp->st_mode))
{
printf("\n\n\nCALLING RECURSIVE DELETE with \"%s\"\n", direntp->d_name);
recursive_return_value = recursive_delete(direntp->d_name);
return_value += recursive_return_value;
if((!switches.continue_if_error) && (recursive_return_value != 0))
{
break;
}
if((!switches.files_only) && (recursive_return_value == 0))
{
if((chdir("..")) == -1)
{
perror("ERROR(6)");
return 1;
}
printf("CDED BACK TO \"%s\" FROM \"%s\"\n", path, direntp->d_name);
if((rmdir(direntp->d_name)) == -1)
{
perror("ERROR(7)");
return 1;
}
if(switches.verbose)
{
printf("DELETED DIRECTORY \"...\\%s\\\"\n\n\n", direntp->d_name);
}
}
}
}
}
return return_value;
}
感謝您的回覆,但我有點失落,因爲這對我有幫助。每次循環開始時聲明direntp是毫無意義的,除非我將dirent結構的實際值複製到不同的結構中,因爲readdir()不使用接收它的返回值的dirent結構的指針地址。另外我想你錯過了理解改變當前目錄的要點。如果我使用上面的代碼,那麼相對路徑是有效的,因爲recurisive_delete()將更改cwd,rmdir(direntp-> d_name)將返回一個No such file或directory error。 – 2013-03-26 22:45:38
你沒看到第二個'chdir()'在最後?我傾向於使用盡可能少的全局變量來避免諸如爭用條件之類的事情,並將相關的代碼和數據緊密結合在一起。 – 2013-03-26 22:56:49
第二個想法是,上面的代碼不會刪除指定的目錄,只會刪除它中的所有內容。我會更新它來解決這個問題。 – 2013-03-26 23:09:51