2016-05-19 3 views
0

私はlsの出力をツリーで表したグラフィカルlsのバージョンを扱っています。私はコードの大半を稼働させていますが、コマンドラインでどのディレクトリを読み込むかを決定できるようにしたいと考えています。私はコマンドラインで指定されたディレクトリを読み込んで、ディレクトリを開いて印刷する方法

DIR *d 
d = opendir(argv[1]); 

を使用して試してみました。しかし、これは動作やファイルなどのファイルを更新していないサイズやその他の情報を開くエラーになりません。

すべての情報をお待ちしております。ありがとう。

#include <sys/types.h> 
#include <sys/stat.h> 

#include <sys/types.h> 
#include <unistd.h> 

#include <stdlib.h> 
#include <dirent.h> 
#include <stdio.h> 
#include <string.h> 


#define _GNU_SOURCE 
#include <limits.h> 

void helper(DIR *, struct dirent *, struct stat, char *, int, char **); 
void dircheck(DIR *, struct dirent *, struct stat, char *, int, char **); 

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

    DIR *d; 

    // Create dirent struct 
    struct dirent *dir; 

    // Create stat struct 
    struct stat buf; 

    // current path for file 
    char currentPath[FILENAME_MAX]; 

    // Depth for tree 
    int depth = 0; 


    // Checking for correct usage 
    if (argc != 2) { 
    printf("Usage: './gls <directory_name>'\n"); 
    exit(0); 
    } 

    // Checking that file provided in command line actually exists 
    if (lstat(argv[(argc - 1)], &buf) < 0) { 
    printf("Error: No such file exists.\n"); 
    return 1; 
    exit(0); 
    } 

    // General resource for printing files: http://stackoverflow.com/questions/4204666/how-to-list-files-in-a-directory-in-a-c-program%20*/ 

    // Open the current directory 
    d = opendir ("."); 

    if(d == NULL) { 
    printf("Error opening directory.\n"); 
    return 1; 
    } 

    // Store the current directory into currentPath 
    if((getcwd(currentPath, FILENAME_MAX)) == NULL) { 
    printf("Error: No such file exists.\n"); 
    return 1; 
    } 

    // Iterate through all items in directory 
    while((dir = readdir(d)) != NULL){ 

    // Do not process . and .. 
    if(strcmp(dir->d_name, ".") == 0 || strcmp(dir->d_name, "..") == 0) 
     continue; 

    // Forms the path for lstat 
    getcwd(currentPath, FILENAME_MAX); 
    strcat(currentPath, "/"); 
    strcat(currentPath, dir->d_name); 
    if(lstat(currentPath, &buf) == -1){ 
     perror("stat"); 
     printf("Error could not open file\n"); 
    } 
    getcwd(currentPath, FILENAME_MAX); 

    // Checks if file is a regular file 
    if(S_ISREG(buf.st_mode)) 
    printf("| %s (regular file - %d - !checksum)\n", dir->d_name, (int)buf.st_size); 

    // Checks if file is a directory 
    else if(S_ISDIR(buf.st_mode)) { 
     printf("| %s (directory)\n", dir->d_name); 
     dircheck(d, dir, buf, currentPath, depth, argv); 
    } 

    // Checks if file is a symbolic link 
    else if(S_ISLNK(buf.st_mode)) { 

     // Resource used for absolute and relative paths: http://www.apiexamples.com/c/stdlib/realpath.html 
     char resolved_path[PATH_MAX]; 
     realpath(currentPath, resolved_path);   
     printf("| %s (symbolic link - %s)\n", dir->d_name, resolved_path); 
    } 

    // Checks if file is a FIFO 
    else if(S_ISFIFO(buf.st_mode)) { 
     printf("| %s (fifo (named pipe))\n", dir->d_name); 
    } 
    } 
    // Close the directory and return 0 for success 
    closedir(d); 
    return 0; 
} 

// Recursive helper 
// Resource used for some of helper function and dircheck function: http://stackoverflow.com/questions/4989431/how-to-use-s-isreg-and-s-isdir-posix-macros 
void helper(DIR *d, struct dirent *dir, struct stat buf, char currentPath[FILENAME_MAX], int depth, char *argv[]){ 
    int i = 0; 

    // Open directory in currentPath 
    if((d = opendir(currentPath)) == NULL) 
    printf("Error: Failed to open Directory ==> %s\n", currentPath); 

    // Read through directory 
    while((dir = readdir(d)) != NULL){ 

    // If file is . or .. ignore 
    if(strcmp(dir->d_name, ".") == 0 || strcmp(dir->d_name, "..") == 0) 
     continue; 

    getcwd(currentPath, FILENAME_MAX); 
    strcat(currentPath, "/"); 
    strcat(currentPath, dir->d_name); 

    getcwd(currentPath, FILENAME_MAX); 

    // If file is a register 
    if(S_ISREG(buf.st_mode)){ 
     for(i = 0; i < depth; i++) { 
     printf(" "); 
     printf("%s (%d bytes)\n", dir->d_name, (int)buf.st_size); 
     } 
    } 

    // If file is a directory 
    if(S_ISDIR(buf.st_mode)) { 
     if(strcmp(dir->d_name, ".") == 0 || strcmp(dir->d_name, "..") == 0) { 
     dircheck(d, dir, buf, currentPath, depth, argv); 
     } 
    } 
    } 

    // Change directory back 
    chdir(".."); 
    closedir(d); 
} 


// Resource used as guideline in order to create helper and dircheck functions 
// http://stackoverflow.com/questions/4989431/how-to-use-s-isreg-and-s-isdir-posix-macros 
void dircheck(DIR *d, struct dirent *dir, struct stat buf, char currentPath[FILENAME_MAX], int depth, char *argv[]){ 

    int i = 0; 
    strcat(currentPath, "/"); 
    strcat(currentPath, dir->d_name); 

    // If two directories exists at the same section in the tree 
    if((chdir(currentPath)) == -1){ 
    getcwd(currentPath, FILENAME_MAX); 
    strcat(currentPath, "/"); 
    strcat(currentPath, dir->d_name); 

    getcwd(currentPath, FILENAME_MAX); 

    // Add --- based on the depth of the tree 
    for(i = 0; i <= depth; i++) 
     printf ("---"); 
    printf("| %s (subdirectory)\n", dir->d_name); 
    depth++; 
    helper(d, dir, buf, currentPath, depth, argv); 
    } 

    else{ 
    // Add --- based on the depth of the tree 
    for(i =0; i <= depth; i++) 
     printf("---"); 
    printf("| %s (subdirectory)\n", dir->d_name); 
    chdir(currentPath); 
    depth++; 
    helper(d, dir, buf, currentPath, depth, argv); 
    } 
} 
+2

をあなただけの一度だけstat' 'を呼び出し、あなたが唯一の引数として与えられたディレクトリにそれを呼び出します。つまり、 'statBuf.st_mode'の値は決して変化しません。 –

+0

無関係な注記では、 'stat'が失敗した場合、それはファイルが存在しないだけでなく、他の多くの理由で起こる可能性があります。何がうまくいかなかったかを知るには、['errno'](http://man7.org/linux/man-pages/man3/errno.3.html)をチェックする必要があります。 –

+0

どうすれば各ファイルを個別にチェックするための値を更新できますか? – AndieM

答えて

1

あなたはstat before whileループを読んでいますが、これはあなたのケースではdirです。 その後、ディレクトリ内のすべてのファイルに対して、st_modeをチェックしていますが、これはwhileループのどこにも更新されません。

+0

どうすれば更新できますか? – AndieM

0
if (stat(argv[(argc - 1)], &statBuf) < 0) 

この行は単にディレクトリ情報を照会するので、あなたは常にディレクトリタイプを取得します。 あなたはあなたがこのようなコードを変更することができ、そのディレクトリの下に を特定のファイルを照会する必要があります

#include <stdio.h> 
#include <dirent.h> 
#include <stdlib.h> 

#include <errno.h> 
#include <string.h> 

#include <sys/types.h> 
#include <sys/stat.h> 

/* Resource: http://stackoverflow.com/questions/4204666/how-to-list-files-in-a-directory-in-a-c-program */ 

/* Resource: http://cboard.cprogramming.com/linux-programming/131-stat.html */ 
#define MAX_FILE_NAME_LEN 256 

int main(int argc, char *argv[]) 
{ 
    char path[MAX_FILE_NAME_LEN] = {0}; 
    struct stat statBuf; 

    if (argc != 2) { 
    printf("Usage: './gls <directory_name>'\n"); 
    exit(0); 
    } 


    if (stat(argv[(argc - 1)], &statBuf) < 0) { 
    printf("Error: No such file exists.\n"); 
    exit(0); 
    } 

    DIR   *d; 
    struct dirent *dir; 
    //char currentPath[FILENAME_MAX]; 

    d = opendir(argv[1]); 


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

    //getcwd(currentPath, FILENAME_MAX); 
    //strcat(currentPath, "/"); 
    //strcat(currentPath, dir->d_name); 
    //if(stat(currentPath, &statBuf) == -1){ 
     //printf("N") 
    //} 
    memset(path, 0, MAX_FILE_NAME_LEN); 
    snprintf(path,MAX_FILE_NAME_LEN,"%s%s",argv[1],dir->d_name); 
    //getcwd(currentPath, FILENAME_MAX); 

    if (stat(path, &statBuf) < 0) { 
    printf("Error: No such file exists.\n"); 
    continue; 
    // exit(0); 
    }                      

    if(S_ISREG(statBuf.st_mode)) { 

     printf("| %s (regular file - %d - !checksum!)\n", dir->d_name, (int)statBuf.st_size);    /* If regular file */ 
    } 

    if(S_ISDIR(statBuf.st_mode)) { 
     printf("| %s (directory - size)\n", dir->d_name); 
    } 

    if(S_ISLNK(statBuf.st_mode)) { 
     printf("| %s (symbolic link - points to !!!\n", dir->d_name); 
    } 

    if(S_ISFIFO(statBuf.st_mode)) { 
     printf("| %s (fifo (named pipe))\n", dir->d_name); 
    } 
    } 

    closedir(d); 

    return(0); 
} 
+0

私はこれらの変更を実装したときにエラーメッセージ "エラー:このようなファイルは何度も存在していますか?"(stat(path、&statBuf)<0)の意味は何ですか? – AndieM

+0

'path' (path(&statBuf)<0)は、指定されたファイルが存在しないことを意味します。 'path'を出力してファイルが存在するかどうかを確認できます。私のために働き、dirとファイルのパーミッションをチェックすることができます。また、perror()を使用して、正確なエラーを見つけることができます – Sunson

+0

@AndieMこのリンクが役立ちます:http://stackoverflow.com/questions/8524876/ c-programming-stat-system-call-error – Sunson

関連する問題