c - 如何读取命令行中给出的目录并打开和打印目录

标签 c linux

我正在研究图形化 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);
  }
}

最佳答案

您正在 while 循环之前读取 stat,在您的情况下这是 dir。 然后对于目录中的每个文件,您正在检查 st_mode,但这在 while 循环中没有更新。

关于c - 如何读取命令行中给出的目录并打开和打印目录,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37314939/

相关文章:

Linux shell脚本由于/usr/bin/sh而出错

linux - 无法在 Gnome 中禁用 PrintScreen 键

linux - 如何使用 Pyinstaller 为 Linux 机器创建可执行文件?

linux - 我的自旋锁有问题吗?

C Gameboy 独立函数和主文件

c - 嵌入式 GCC 优化魔法

C - 需要检测数字中是否存在数字(hw)

c - 初学者C指针问题

c - Windows 中的消息框以韩语或中文显示

java - OpenShift Maven 没有使用正确的 JAVA_HOME