要求
mustkown
struct __dirstream
{
void *__fd;
char *__data;
int __entry_data;
char *__ptr;
int __entry_ptr;
size_t __allocation;
size_t __size;
__libc_lock_define (, __lock)
};
typedef struct __dirstream DIR;
struct dirent
{
long d_ino; /* inode number 索引节点号 */
off_t d_off; /* offset to this dirent 在目录文件中的偏移 */
unsigned short d_reclen; /* length of this d_name 文件名长 */
unsigned char d_type; /* the type of d_name 文件类型 */
char d_name [NAME_MAX+1]; /* file name (null-terminated) 文件名,最长255字符 */
}
struct stat
{
dev_t st_dev; /* ID of device containing file */ //文件使用的设备号
ino_t st_ino; /* inode number */ //索引节点号
mode_t st_mode; /* protection */ //文件对应的模式,文件,目录等
nlink_t st_nlink; /* number of hard links */ //文件的硬连接数
uid_t st_uid; /* user ID of owner */ //所有者用户识别号
gid_t st_gid; /* group ID of owner */ //组识别号
dev_t st_rdev; /* device ID (if special file) */ //设备文件的设备号
off_t st_size; /* total size, in bytes */ //以字节为单位的文件容量
blksize_t st_blksize; /* blocksize for file system I/O */ //包含该文件的磁盘块的大小
blkcnt_t st_blocks; /* number of 512B blocks allocated */ //该文件所占的磁盘块
time_t st_atime; /* time of last access */ //最后一次访问该文件的时间
time_t st_mtime; /* time of last modification */ //最后一次修改该文件的时间
time_t st_ctime; /* time of last status change */ //最后一次改变该文件状态的时间
};
最后,总结一下,想要获取某目录下(比如a目下)b文件的详细信息,我们应该怎样做?
首先,我们使用opendir
函数打开目录a,返回指向目录a的DIR结构体c。
接着,我们调用readdir
©函数读取目录a下所有文件(包括目录),返回指向目录a下所有文件的dirent结构体d。
然后,我们遍历d,调用stat(d->name,stat *e)
来获取每个文件的详细信息,存储在stat结构体e中。
总体就是这样一种逐步细化的过程,在这一过程中,三种结构体扮演着不同的角色。
dir c = opendir(a)
dirent d readdir(c)
stat e
stat(d->name,&e)
//通过上述四步即可在stat结构体e中得到a目录下的b文件的信息
废话不说了,直接上码!
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <dirent.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <pwd.h>
#include <linux/limits.h>
#include <grp.h>
#include <unistd.h>
#include <time.h>
//lstriRa 参数
#define l 1
#define s 2
#define t 3
#define r 4
#define i 5
#define R 6
#define a 7
struct info
{
char filename[4096];
struct stat otherinfo;
};
//ls
void myls(int arameter[], char* path);
void printfinfo(int arameter[], int filenum, struct info *temp, int count);
//ls -l
void myls_l(struct info *temp);
void uidtostring(gid_t uid);
void gittostring(gid_t gid);
void modetostring(struct stat otherinfo);//文件权限
//ls -r
static struct info *myls_r(struct info **temp, int num);
//ls -t
static struct info *myls_t(struct info **temp, int num);
//ls -R
void myls_R(struct info *temp, int num, int arameter[], char *path);
int main(int argc, char *argv[])
{
int arameter[8] = {
0}; // 存参数
char path[4096]; // 目录
int null[8] = {
0};
char pathname[4096]; // 多路径读取
getcwd(path, sizeof(path)); // 获取文件路径
if (argc == 1)
{
strcpy(path, "./");
path[2] = '\0';
myls(null, path);
return 0;
}
for (int y = 1; y < argc; y++)
{
if (argv[y][0] != '-')
{
strcpy(path, argv[y]);
}
}
int arameternum = 0;
for (int x = 1; x < argc; x++)
{
arameternum += strlen(argv[x]); // 参数长度
}
while (arameternum > 1)
{
int x = getopt(argc, argv, "lstriRa");
if (x < 0)
{
break;
}
else
{
if (x == 'l')
arameter[l] |= 1;
if (x == 's')
arameter[s] |= 1;
if (x == 't')
arameter[t] |= 1;
if (x == 'r')
arameter[r] |= 1;
if (x == 'i')
arameter[i] |= 1;
if (x == 'R')
arameter[R] |= 1;
if (x == 'a')
arameter[a] |= 1;
}
arameternum--;
}
int flag = 0;
for (int n = 1; n < argc; n++)
{
chdir(pathname);
if (argv[n][0] != '-')
{
strcpy(path, argv[n]);
printf("%s:\n", path);
myls(arameter, path);
printf("\n");
flag++;
}
}
if (flag == 0)
{
strcpy(path, pathname);
myls(arameter, path);
}
return 0;
}
// ls
void myls(int arameter[], char *path)
{
chdir(path); // 跳转至path指定的目录'
DIR *dir = NULL;
struct dirent *ptr = NULL;
int size = 0;
int sizehavea = 0;
int filenum = 0;
int num = 0;
struct info *temp = (struct info *)malloc(sizeof(struct info) * 4096);
memset(temp, 0, sizeof(struct info) * 4096); // 分配内存+置0
struct info *inception = temp;
if ((dir = opendir(path)) == NULL)
{
perror("fail:");
exit(1);
}
while ((ptr = readdir(dir)) != NULL)
{
strcpy(temp->filename, ptr->d_name);
stat(ptr->d_name, &(temp->otherinfo));
sizehavea += (temp->otherinfo.st_size);
if ((temp->filename[0]) != '.')
{
size += temp->otherinfo.st_size;
}
temp++;
filenum++;
}
num = filenum;
temp = inception;
if (arameter[R] == 1)
{
printf("%s:\n", path);
myls_R(temp, num, arameter, path);
}
if (arameter[R] != 1)
{
printfinfo(arameter, num, temp, filenum);
}
free(temp);
closedir(dir);
}
// ls -l
void myls_l(struct info *temp)
{
modetostring(temp->otherinfo);
printf("%5ld", temp->otherinfo.st_nlink);
uidtostring(temp->otherinfo.st_uid);
gittostring(temp->otherinfo.st_gid);
printf("%ld\t", temp->otherinfo.st_blksize / 2);
char *time = ctime(&(temp->otherinfo.st_mtime));
if (time[strlen(time) - 1] == '\n')
time[strlen(time) - 1] = '\0';
printf("%-12s\t", time);
}
// ls -r
static struct info *myls_r(struct info **temp, int num)
{
for (int x = 0; x <= (num - 1) / 2; x++)
{
struct info tmp = (*temp)[num - 1 - x];
(*temp)[num - x - 1] = (*temp)[x];
(*temp)[x] = tmp;
}
return *temp;
}
// ls -t
static struct info *myls_t(struct info **temp, int num)
{
for (int x = 1; x < num; x++)
{
for (int j = 0; j < num - x; j++)
{
if ((*temp + j)->otherinfo.st_mtime < (*temp + j + 1)->otherinfo.st_mtime)
{
struct info tmp = (*temp)[j + 1];
(*temp)[j + 1] = (*temp)[j];
(*temp)[j] = tmp;
}
}
}
return *temp;
}
// ls -R
void myls_R(struct info *temp, int num, int arameter[], char *path)
{
if (arameter[t] == 1)
{
temp = myls_t(&temp, num);
}
if (arameter[r] == 1)
{
temp = myls_r(&temp, num);
}
for (int m = 0; m < num; m++)
{
char *tmp = (temp + m)->filename;
if (arameter[a] != 1)
{
if (arameter[i] == 1 && tmp[0] != '.')
printf("%-10ld ", (temp + m)->otherinfo.st_ino);
if (arameter[s] == 1 && tmp[0] != '.')
printf("%-4ld ", (temp + m)->otherinfo.st_blocks / 2);
if (arameter[l] == 1 && tmp[0] != '.')
myls_l((temp + m));
if (tmp[0] != '.')
printf("%s ", (temp + m)->filename);
if (arameter[l] == 1 && tmp[0] != '.')
printf("\n");
}
if (arameter[a] == 1)
{
if (arameter[i] == 1)
printf("%-10ld ", (temp + m)->otherinfo.st_ino);
if (arameter[s] == 1)
printf("%-4ld ", (temp + m)->otherinfo.st_blocks / 2);
if (arameter[l] == 1)
myls_l((temp + m));
printf("%s ", (temp + m)->filename);
if (arameter[l] == 1)
printf("\n");
}
}
printf("\n");
for (int m = 0; m < num; m++)
{
char *tmp = (temp + m)->filename;
if (S_ISDIR((temp + m)->otherinfo.st_mode) && tmp[0] != '.')
{
char path1[1024];
char path2[1024];
strcpy(path1, path);
strcpy(path2, path1);
strcat(path2, "/");
strcat(path2, (temp + m)->filename);
myls(arameter, path2);
}
}
}
// 格式打印
void printfinfo(int arameter[], int filenum, struct info *temp, int count)
{
if (arameter[t] == 1)
{
temp = myls_t(&temp, count);
}
if (arameter[r] == 1)
{
temp = myls_r(&temp, count);
}
while (filenum > 0)
{
char *tmp = temp->filename;
if (arameter[a] != 1)
{
if (arameter[i] == 1 && tmp[0] != '.')
printf("%-10ld ", temp->otherinfo.st_ino);
if (arameter[s] == 1 && tmp[0] != '.')
printf("%-4ld ", temp->otherinfo.st_blocks / 2);
if (arameter[l] == 1 && tmp[0] != '.')
myls_l(temp);
if (tmp[0] != '.')
printf("%-12s\t ", temp->filename);
if (arameter[l] == 1 && tmp[0] != '.')
printf("\n");
}
if (arameter[a] == 1)
{
if (arameter[i] == 1)
printf("%-10ld ", temp->otherinfo.st_ino);
if (arameter[s] == 1)
printf("%-4ld ", temp->otherinfo.st_blocks / 2);
if (arameter[l] == 1)
myls_l(temp);
printf("%-12s\t ", temp->filename);
if (arameter[l] == 1)
printf("\n");
}
filenum--;
temp++;
}
}
// uid
void uidtostring(uid_t uid)
{
struct passwd *pw_ptr;
static char numstr[10];
if ((pw_ptr = getpwuid(uid)) == NULL)
{
printf("%8d", uid);
}
else
{
printf("%8s", pw_ptr->pw_name);
}
}
// gid
void gittostring(gid_t gid)
{
struct group *grp_ptr;
static char numstr[10];
if ((grp_ptr = getgrgid(gid)) == NULL)
{
printf("%8d", gid);
}
else
{
printf("%8s", grp_ptr->gr_name);
}
}
// 文件权限
void modetostring(struct stat otherinfo)
{
int mode = otherinfo.st_mode;
char str[4096] = {
0};
strcpy(str, "----------");
if (S_ISDIR(mode))
str[0] = 'd';
if (S_ISCHR(mode))
str[0] = 'c';
if (S_ISBLK(mode))
str[0] = 'b';
if (mode & S_IRUSR)
str[1] = 'r';
if (mode & S_IWUSR)
str[2] = 'w';
if (mode & S_IXUSR)
str[3] = 'x';
if (mode & S_IRGRP)
str[4] = 'r';
if (mode & S_IWGRP)
str[5] = 'w';
if (mode & S_IXGRP)
str[6] = 'x';
if (mode & S_IROTH)
str[7] = 'r';
if (mode & S_IWOTH)
str[8] = 'w';
if (mode & S_IXOTH)
str[9] = 'x';
printf("%12s", str);
}
//此为鄙人的拙见,如有不正,请指正,该代码未实现颜色展示,颜色展示可以用``printf()`` 中的``033[``命令,别问我为啥没写,问就是懒,哼!
//该代码在ArchLinux系统中适配,其他系统未尝试,别问我为啥没测,问就是懒,哼!
//如有其他问题,请私信联系我。