小白第一篇
最近跟着大佬学习了文件IO,然后就被大佬安排使用C语言实现"ll"(查看文件详细信息)命令。
第一步:看需求
由图可知,需要获取7列信息分别为:文件属性,文件硬链接数,文件拥有者,文件拥有者所在组,文件字节数,创建时间,文件名。
第二步 找方法
焦头烂额,也没想到有什么好方法,于是再次找上大佬。
佬:你傻啊,你可以使用lstat函数(一个可以获取文件信息的函数)。
我:???
佬:你不知道,你就去man它啊!光看着我有啥用。
于是:
man lstat
头文件如下:
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
原函数如下:
int lstat(const char *pathname, struct stat *statbuf);
这对我也太友好了,看看有什么我能用上的:
struct stat {
dev_t st_dev; /* ID of device containing file */
ino_t st_ino; /* Inode number */
mode_t st_mode; /* File type and mode 文件属性可用 */
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; /* Block size for filesystem I/O */
blkcnt_t st_blocks; /* Number of 512B blocks allocated */
struct timespec st_atim; /* Time of last access */
struct timespec st_mtim; /* Time of last modification */
struct timespec st_ctim; /* Time of last status change */
#define st_atime st_atim.tv_sec /* Backward compatibility */
#define st_mtime st_mtim.tv_sec /* 创建时间可用*/
#define st_ctime st_ctim.tv_sec
};
第三步 写代码
1 文件属性
switch (sb.st_mode & S_IFMT) {
case S_IFBLK: printf("block device\n"); break;//判断是否为块设备文件
case S_IFCHR: printf("character device\n"); break;//判断是否为字符特殊文件
case S_IFDIR: printf("directory\n"); break;//判断是否为目录
case S_IFIFO: printf("FIFO/pipe\n"); break;//判断是否为管道文件
case S_IFLNK: printf("symlink\n"); break;//判断是否为符号连接
case S_IFREG: printf("regular file\n"); break;//判断是否为普通文件
case S_IFSOCK: printf("socket\n"); break;//判断是否为套接字文件
default: printf("unknown?\n"); break;
}
//文件属性代码
switch(statbuf.st_mode & S_IFMT){//判断文件类型
case S_IFSOCK:
printf("s");
break;
case S_IFLNK:
printf("l");
break;
case ......
.....
.....
就这样,就完成了第一列的第一小列。接下来,就需要判断文件的读写执行属性了。依旧是使用st_mode。
while(n >= 0){
if(statbuf.st_mode & 1 << n){
switch(n % 3){
case 2:
printf("r");
break;
case 1:
printf("w");
break;
case 0:
printf("x");
break;
}
}
else{
printf("-");
}
n--;
}
2.文件硬链接数
//文件硬链接数代码
printf(" %ld",statbuf.st_nlink);
3.文件拥有者
由于文件提供了ID号给我,所以我需要getpwuid函数转换一下
#include <sys/types.h>
#include <pwd.h>
struct passwd *getpwuid(uid_t uid);
//文件拥有者代码
struct passwd *p_uid;
p_uid = getpwuid(statbuf.st_uid);
printf(" %s",p_uid->pw_name);
4.文件拥有者所在组
getgrgid()用法同getpwuid()
//文件拥有者所在组代码
struct group *p_gid;
p_gid = getgrgid(statbuf.st_gid);
printf(" %s",p_gid->gr_name);
5.文件字节数
//文件字节数代码
printf("%7ld",statbuf.st_size);
6.创建时间
由于提供给我的时间是一个结构体,所以需要进行适当修改。
//创建时间代码
struct tm *tp = localtime(&statbuf.st_mtime);
printf(" %d月 %d %d:%02d",
tp->tm_mon + 1,
tp->tm_mday,
tp->tm_hour,
tp->tm_min);
至此,查询当前目录下的所有文件详细信息就完成了。
大佬:什么?只能查询当前目录,那有何用。
我:好的好的,我改.......
回头看看需求,我这次是要去其他目录,这次我学聪明了,就先进行了"学习"。
先B了一下
再C了一下
就这样,我学了一个新的函数,叫做readdir()
man readdir
#include <dirent.h>
struct dirent *readdir(DIR *dirp);
//目录读取代码
DIR * dir;
struct dirent * ptr;
dir = opendir(argv[1]);
char str[20];
while((ptr = readdir(dir)) != NULL){
strcpy(str,argv[1]);
strcat(str,"/");//路径必备 “/”
get_stat(strcat(str,ptr->d_name));//将文件信息封装成了函数
printf(" %s\n",ptr->d_name);//文件名
·······························································最后的结果是这样的··································································
············································································和这样的···································································
我兴高采烈的拿去给大佬看,然后,
佬:还不错,能做出来,但你自己回去还是再想哈,为什么还有这样的?
写在结尾:我还没想通,有知道原因且愿意告知的请告知,谢谢。再次欢迎各位大佬批评改正。