ls -l:
farsight@ubuntu:~/px/IO进线程/dir$ ls -l
total 24
-rwxrwxr-x 1 farsight farsight 7599 8月 25 05:16 a.out
-rw-rw-r-- 1 farsight farsight 2797 8月 25 05:16 lstat.c
-rw-rw-r-- 1 farsight farsight 2797 8月 25 05:15 lstat.c~
-rw-rw-r-- 1 farsight farsight 535 8月 10 05:21 opendir.c
-rw-rw-r-- 1 farsight farsight 692 8月 10 05:34 readdir.c
获取文件属性 --- lstat()
相关结构体为:
struct stat
{
mode_t st_mode;//文件类型
nlink_t st_nlink;//文件硬连接数
uid_t st_uid;//用户ID
gid_t st_gid;//用户组ID
off_t st_size;//文件大小
struct timespec st_mtim;//最后修改文件的时间
#define st_mtim,tv_sec
}
getgrgid--得到用户组名的函数
getpwuid--得到用户名的函数
由该函数的结构体可知,硬连接数、用户名、用户组名、文件大小、文件名都可以直接获得,修改文件的时间则需借助 locatime 函数获取,比较复杂的就是获取文件类型和文件权限了。
下面分别分析文件类型和文件权限的获取方法:
(1)文件类型的获取
获取文件类型对应有一下宏:
S_IFMT 0170000 bit mask for the file type bit filed --- 文件类型掩码
S_IFSOCK 0140000 socket --- 套接字
S_IFLNK 0120000 symbolic link --- 链接文件
S_IFREG 0100000 regular file --- 普通文件
S_IFBLK 0060000 block device --- 块设备文件
S_IFDIR 0040000 directory --- 目录文件
S_IFCHR 0020000 character device --- 字符设备文件S_IFIFO 0010000 FIFO --- 管道文件
判断方法:如果 st_mode & S_TFMT 等于对应文件类型宏,则文件类型宏对应类型就为文件类型
(2) 文件权限的获取
用户权限
S_IRUSR 00400 owner has read permission
S_IWUSR 00200 owner has write permission
S_IXUSR 00100 owner has execute permission
用户组权限S_IRGRP 00040 group has read permission
S_IWGRP 00020 group has write permission
S_IXGRP 00010 group has execute permission
其他用户权限
S_IROTH 00004 others have read permission
S_IWOTH 00002 others have write permission
S_IXOTH 00001 others have execute permission
判断方法:st_mode & 对应权限宏 == 宏本身 表示具有该权限
如果直接用 if 来判断,虽然直观,但是麻烦,这里可以用循环左移依次与对应权限宏相与,例如:左移8位、5位、2位,都对应写权限,左移7位、4位、1位:执行权限
代码:
#include <stdio.h>
#include <sys/types.h>
#include <dirent.h>
#include <sys/stat.h>
#include <unistd.h>
#include <time.h>
#include <grp.h>
#include <pwd.h>
int main()
{
int ret = 0;
int i;
int x = 1;
struct stat info;//创建存放信息的结构体
struct tm *t = NULL; //存放时间信息的结构体
struct group *gp = NULL; //存放用户组信息的结构体
struct passwd *usr = NULL; //存放用户信息的结构体
DIR *dir = opendir(".");//打开当前目录得到目录流指针
if(NULL == dir)
{
perror("opendir");
return -1;
}
struct dirent *buf = NULL;
//读取目录,即显示当前目录下的文件名
while((buf = readdir(dir)) != NULL)//循环遍历目录得到每一个目录项,不为空表示读到了目录
{
if(buf->d_name[0] != '.')//不显示隐藏文件(第一个元素不为".")
{
ret = lstat(buf->d_name, &info);//通过文件名得到文件信息
if(ret < 0)
{
perror("lstat");
return -1;
}
switch(info.st_mode & S_IFMT)
{
case S_IFREG:
printf("-");//普通文件
break;
case S_IFDIR:
printf("d");//目录文件
break;
case S_IFSOCK:
printf("s");//套接字
break;
case S_IFLNK:
printf("l");//链接文件
break;
case S_IFBLK:
printf("b");//块设备文件
break;
case S_IFIFO:
printf("p");//管道文件
break;
case S_IFCHR:
printf("c");//字符设备文件
break;
}
for(i = 8; i >= 0; i--)
{
if(info.st_mode & (x << i))//x左移i位
{
switch(i%3)
{
case 2:
printf("r");//第8、5、2位都是r权限
break;
case 1:
printf("w");//第7、4、1位都是r权限
break;
case 0:
printf("x");//第6、3、0位都是r权限
break;
}
}
else
{
printf("-");//没有权限
}
}
printf(" %ld ", info.st_nlink); //打印硬链接数
usr = getpwuid(info.st_uid);
printf("%s ", usr->pw_name); //打印用户名
gp = getgrgid(info.st_gid);
printf("%s ", gp->gr_name); //打印用户组名
printf("%-8ld ", info.st_size); //打印文件大小
t = localtime(&info.st_mtime);
printf("%d月 %d %02d:%02d ", t->tm_mon, t->tm_mday, t->tm_hour, t->tm_min); //打印最后一次修改文件时间
printf("%s\n", buf->d_name); //打印文件名
}
}
closedir(dir);
return 0;
}
farsight@ubuntu:~/dir$ ./a.out
-rw-rw-r-- 1 farsight farsight 2797 8月 25 05:16 lstat.c~
-rw-rw-r-- 1 farsight farsight 692 8月 10 05:34 readdir.c
-rwxrwxr-x 1 farsight farsight 7599 8月 8 08:17 a.out
-rw-rw-r-- 1 farsight farsight 2797 8月 26 01:47 lstat.c
-rw-rw-r-- 1 farsight farsight 535 8月 10 05:21 opendir.c