ls -l <文件名>
ls -i <文件名>
查看文件(唯一)的 inode号。
stat
定义 stat 结构体变量
struct stat <变量名>;
stat 函数的使用
int stat(const char *path, struct stat *buf);
功能:获取文件属性
参数:path:文件路径名
buf:保存文件属性信息的结构体
返回值:成功:0
失败:-1
struct stat {
dev_t st_dev; /* 设备包含文件的ID */
ino_t st_ino; /* inode号 */
mode_t st_mode; /* 文件类型和权限 */
nlink_t st_nlink; /* 硬链接数 */
uid_t st_uid; /* 用户ID */
gid_t st_gid; /* 组ID */
off_t st_size; /* 大小 */
dev_t st_rdev; /* 设备ID */
time_t st_atime; /* 最后访问时间 */
time_t st_mtime; /* 最后修改时间 */
time_t st_ctime; /* 最后状态改变时间 */
};
if (stat("路径", &结构体变量) < 0){
perror("提示语句");
return -1;
}
访问成员变量
st_mode 与 文件类型
文件类型和权限:st_mode
e.g. 33204(10) ---> 0100664(8)
0100664(8):
最高两位(不包含八进制标志位0),即 10 两位:
和 S_IFMT 执行按位与操作,可得文件类型
或直接使用下面的方法来判断文件类型:
st_mode 与 rwx 权限
文件类型和权限:st_mode
e.g. 33204(10) ---> 0100664(8)
0100664(8):
第三位(不包含八进制标志位0),即 664 前的 0:见下图
后三位:用户、组用户、其他用户的操作权限
实现 ls - l <文件名> 功能
1)确定文件类型
方法一:
方法二:
2)确定三组权限值
其他两组与之类似。不过,此法可优化:
// 确定三组权限值
char right[3] = "rwx";
for (int i = 0; i < 9; i++)
(st.st_mode & (0400 >> i)) ? printf("%c", right[i%3]): printf("-");
3)确定硬链接数
printf("%d", 结构体变量名.st_nlink);
4)确定用户名和组名
struct passwd *getpwuid(uid_t uid);
功能:通过用户 id 获取用户属性
参数:uid:用户 id
返回值:返回保存用户相关属性结构体的地址
失败:NULL
struct passwd {
char *pw_name; /* 用户名 */
char *pw_passwd; /* 密码 */
uid_t pw_uid; /* user ID */
gid_t pw_gid; /* group ID */
char *pw_gecos; /* 真实名 */
char *pw_dir; /* 主目录 */
char *pw_shell; /* 使用的shell */
};
struct group *getgrgid(gid_t gid);
功能:通过组 id 获取组属性
参数:gid:组 id
返回值:返回保存组相关属性结构体的地址 err:NULL
struct group {
char *gr_name; /* 组名 */
char *gr_passwd; /* 组密码 */
gid_t gr_gid; /* 组ID */
char **gr_mem; /*组成员账号 */
};
5)确定文件大小
printf("%d", 结构体变量名.st_size);
6)获取最后一次更改时间
char *ctime(const time_t *timep);
功能:将时间秒数转化为字符串表示
参数:timep :时间
返回值:成功返回字符串首地址,失败:NULL
7)*整合实现
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <pwd.h>
#include <grp.h>
#include <time.h>
int main(int argc, char const *argv[])
{
struct stat st;
if (stat(argv[1], &st) < 0){
perror("Failed: ");
return -1;
}
switch (st.st_mode & S_IFMT)
{
case S_IFSOCK:
putchar('s');
break;
case S_IFLNK:
putchar('l');
break;
case S_IFREG:
putchar('-');
break;
case S_IFBLK:
putchar('b');
break;
case S_IFCHR:
putchar('c');
break;
case S_IFIFO:
putchar('p');
break;
case S_IFDIR:
putchar('d');
break;
default:
break;
}
if (st.st_mode & S_IRUSR)
putchar('r');
else
putchar('-');
if (st.st_mode & S_IWUSR)
putchar('w');
else
putchar('-');
if (st.st_mode & S_IXUSR)
putchar('x');
else
putchar('-');
if (st.st_mode & S_IRGRP)
putchar('r');
else
putchar('-');
if (st.st_mode & S_IWGRP)
putchar('w');
else
putchar('-');
if (st.st_mode & S_IXGRP)
putchar('x');
else
putchar('-');
if (st.st_mode & S_IROTH)
putchar('r');
else
putchar('-');
if (st.st_mode & S_IWOTH)
putchar('w');
else
putchar('-');
if (st.st_mode & S_IXOTH)
putchar('x');
else
putchar('-');
putchar(32);
printf("%d", st.st_nlink);
putchar(32);
printf("%s", getpwuid(st.st_uid)->pw_name);
putchar(32);
printf("%s", getgrgid(st.st_gid)->gr_name);
putchar(32);
printf("%ld", st.st_size);
putchar(32);
printf("%.12s", ctime(&st.st_mtime)+4);
putchar(32);
printf("%s", argv[1]);
putchar(10);
return 0;
}
switch(st.st_mode & S_IFMT){…} 可作如下替换:
确定三组权限值可优化:
运行结果如下:
实现计时器
编程读写一个文件 test.txt,每隔 1秒 向文件中写入一行数据。
该程序应该无限循环,直到按 Ctrl+C 中断程序。
再次启动程序写文件时可以追加到原文件之后,并且序号能够接续上次的序号.
#include <stdio.h>
#include <time.h>
#include <string.h>
#include <unistd.h>
int main(int argc, char const *argv[])
{
FILE *fp = fopen(argv[1], "a+");
if (fp == NULL){
perror("Failed: ");
return -1;
}
char arr[1024] = {};
int row = 0;
while (fgets(arr, 1024, fp))
{
if (arr[strlen(arr)-1] == '\n')
row++;
}
time_t t;
struct tm *now;
while (1){
fprintf(fp, "%d\t", ++row);
time(&t);
now = localtime(&t);
fprintf(fp, "%d-%02d-%02d ", now->tm_year+1900, now->tm_mon+1, now->tm_mday);
fprintf(fp, "%02d:%02d:%02d \n", now->tm_hour, now->tm_min, now->tm_sec);
sleep(1);
fflush(fp); // 若不加此句,则 缓冲区满 或 程序结束 才打印到文件中
}
fclose(fp);
return 0;
}
运行结果如下: