首页 > 解决方案 > 我需要帮助在 C 中获取文件信息

问题描述

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <dirent.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <pwd.h>
#include <grp.h>
#include <time.h>

// This program is pretty much a simulation of the ls command. Find out how to scan all of the files
// in the directory it's being run in and print out all the file names. Has to be in order.

int main(int argc, char* argv[])
{   
    // Don't worry about the else if, this is just a second part of my code that does not work entirely.
    else if (strstr(argv[1], "-i")) // Long output
    {
        char **words = calloc(1000, sizeof(*words));
        
        DIR *d;
        struct dirent *dir;  // Pointer for directory entry 
        d = opendir(".");
        char* a = ".";
        char* b = "..";
        char* c = "ls";
        int ret1, ret2, ret3, count = 0;
        
        
        if (d)  // opendir returns NULL if couldn't open directory
        {
            while ((dir = readdir(d)) != NULL)
            {
                ret1 = strcmp(dir->d_name, a); // Compare with the parent directory.
                ret2 = strcmp(dir->d_name, b); // Compare with the parent directory.
                ret3 = strcmp(dir->d_name, c); // Compare with the ls
                
                if (ret1 == 0 || ret2 == 0 || ret3 == 0)
                {
                    // Skip the ., .., and ls
                }
                else
                {
                    words[count] = strdup(dir->d_name); // Put the file name in the array.
                    count++;
                }
            }
            
            for (int i = 0; i < count; ++i) // Start readjusting the array in alphabetical order.
            {
                int imin = i;
                for (int j = i + 1; j < count; ++j)
                {
                    char word1[1000], word2[1000];
                    strcpy(word1, words[j]);
                    strcpy(word2, words[imin]);
                    for(int p = 0; word1[p]; p++)
                    {
                        word1[p] = tolower(word1[p]);
                    }
                    for(int p = 0; word2[p]; p++)
                    {
                        word2[p] = tolower(word2[p]);
                    }
                    if (strcmp(word1, word2) < 0)
                    {
                        imin = j;
                    }
                }
                char *tmp = words[i];
                words[i] = words[imin];
                words[imin] = tmp;
            }
            
            // Print every word in the array, but this time with metadata!
            struct stat meta;
            for (int i = 0; i < count; ++i)
            {
                stat(words[i], &meta);
                int size = meta.st_size;
                
                // How am I supposed to get read, write, execute info???
                
                struct passwd *p;
                struct group *grp;
                uid_t uid = 0;
                gid_t gid = 0;
                
                if ((p = getpwuid(uid)) == NULL) // If username doesn't exist
                {
                    printf("%d ", meta.st_uid); // User id
                }
                else
                {
                    printf("%s ", p->pw_name); // User Name
                }
                
                if ((grp = getgrgid(gid)) == NULL) // If group name doesn't exist
                {
                    printf("%d ", meta.st_gid); // Group id
                }
                else
                {
                    printf("%s ", grp->gr_name); // Group Name
                }
                
                printf("%d ", size); // File Size
                
                printf("%s ", ctime(&meta.st_mtime)); // bad date format
                
                // I don't want the file name moving down. 
                
                printf("%s \n", words[i]); // File name
            }
            
        }   
        // Closing and freeing
        closedir(d);
        for (int a = 0; a < 1000; ++a)
        {
            free(words[a]);
        }
        free(words);
        
        return 0;
    }
}

目前我的代码给出了这个输出。

root root 435 Tue Oct  5 23:52:59 2021
 find.c 
root root 4562 Fri Oct  8 15:31:23 2021
 ls.c 
root root 58 Wed Oct  6 00:14:25 2021
 Makefile 
root root 296 Wed Oct  6 00:04:37 2021
 tree.c 

我的问题是它应该是这种格式。-rwxrw-r-- tim users 1252 Sep 28 14:00 find.c

第一个“-”应该是一个文件(-)或目录(d)的指示符,然后检查、读取、写入、执行用户、组和其他人的权限,然后是用户名(或用户id),组名(或组 ID),然后是文件大小,然后是修改时间,然后是文件名。

  1. 我不知道如何检查某个东西是文件还是目录。
  2. 我试过查找读取权限的方法,但都没有奏效。
  3. 我输出的日期格式与我试图获得的输出不匹配,我不知道如何修复它。
  4. 使用我当前使用的日期格式,文件名被放在一行中,我不希望这样。

谁能帮我解决这个问题?

标签: arrayscfilemetadata

解决方案


文件名之前的换行符是因为ctime()返回一个以换行符结尾的字符串。所以你应该删除它。

char *time = ctime(&meta.st_mtime);
time[strlen(time)-1] = '\0'; // remove newline
printf("%s ", time);

要确定文件类型,请参阅检查文件是目录还是文件

要将权限转换为符号形式,请参阅在 C 中使用 stat(2) 打印文件权限,例如 'ls -l'


推荐阅读