一、目录和文件
获取文件的属性信息:
stat(文件路径,文件属性结构体):通过文件路径获取到文件的属性,获取到的文件属性回填到文件属性结构体中
返回值:成功返回0,失败返回-1并设置errno
文件属性结构体的构成:
st_dev:包含该文件的设备号
st_ino:inode号
st_mode:文件的类型和权限信息
st_nlink:硬链接数
st_uid:用户id
st_gid:组id
st_rdev:设备id号
st_size:文件大小,单位字节
st_blksize:块的大小
st_blocks:块数
st_atime:最后一次访问时间
st_mtime:最后一次修改时间
st_ctime:最后一次改变时间(只属性,也就是亚数据)
做一个flen的案列
st_mode值判定文件类型的带参宏使用:
S_ISREG(m):是否是普通文件 m----->s.st_mode
S_ISDIR(m):是否是目录文件
S_ISCHR(m):是否是字符设备文件
S_ISBLK(m):是否是块设备文件
S_ISFIFO(m):是否是管道文件
S_ISLNK(m):是否是符号链接文件
S_ISSOCK(m):是否是网络套接字文件
例子:
static char getflty(struct stat s)
{
if(S_ISREG(s.st_mode))
return '-';
if(S_ISDIR(s.st_mode))
return 'd';
if(S_ISCHR(s.st_mode))
return 'c';
if(S_ISBLK(s.st_mode))
return 'b';
if(S_ISFIFO(s.st_mode))
return 'p';
if(S_ISLNK(s.st_mode))
return 'l';
if(S_ISSOCK(s.st_mode))
return 's';
}
st_mode值判定文件类型及权限的宏值使用:
S_IFMT:文件类型的字段位,使用st_mode
按位与上该宏值得到的结果与以下比较判断文件的类型
S_IRWXU:文件所属主用户的权限段位,使用st_mode按位与上该宏值得到的结果如果为真那么
代表该文件拥有可读可写可执行的权限
S_IRUSR:文件所主组用户的可读权限
S_IWUSR:文件所主组用户的可写权限
S_IXUSR:文件所主组用户的可执行权限
S_IRWXG:文件所属组用户的权限段位,使用st_mode按位与上该宏值得到的结果如果为真那么
代表该文件所属组拥有可读可写可执行的权限
S_IRGRP:文件所属组用户的可读权限
S_IWGRP:文件所属组用户的可写权限
S_IXGRP:文件所属组用户的可执行权限
S_IRWXO:其他用户的权限段位,使用st_mode按位与上该宏值得到的结果如果为真那么
代表该文件其他用户拥有可读可写可执行的权限
用户的读写执行权限
S_IROTH:其他用户的可读权限
S_IWOTH:其他用户的可写权限
S_IXOTH:其他用户的可执行权限
char *getquanxian(struct stat s)
{
//char arr[10];
char *arr = malloc(10);
arr[0] = s.st_mode & S_IRUSR ? 'r':'-';
arr[1] = s.st_mode & S_IWUSR ? 'w':'-';
arr[2] = s.st_mode & S_IXUSR ? 'x':'-';
arr[3] = s.st_mode & S_IRGRP ? 'r':'-';
arr[4] = s.st_mode & S_IWGRP ? 'w':'-';
arr[5] = s.st_mode & S_IXGRP ? 'x':'-';
arr[6] = s.st_mode & S_IROTH ? 'r':'-';
arr[7] = s.st_mode & S_IWOTH ? 'w':'-';
arr[8] = s.st_mode & S_IXOTH ? 'x':'-';
arr[9] = '\0';
return arr;
}
fstat(文件描述符,文件属性结构体):通过文件描述符获取到文件的属性,获取到的文件属性回填到文件属性结构体中
返回值:成功返回0,失败返回-1并设置errno
lstat(文件路径,文件属性结构体):和stat函数的功能是一致的,但在获取符号链接文件时两个函数有一定的区别,
sata获取到的是符号链接指向的文件的属性,而lstat获取到的是符号链接本身的权限
文件权限更改:
chmod(文件路径,权限值):更改指定路径文件的权限,成功返回0,失败返回-1并且设置errno
fchmod(文件描述符,权限值):更改指定已打开文件的权限,成功返回0,失败返回-1并且设置errno
unlink(文件路径):从磁盘中删除一个文件,成功返回0,失败返回-1并设置errno
link(原文件,新的硬链接文件):为一个指定文件创建一个硬链接文件,成功返回0,失败返回-1并设置errno
rename(原文件,新的文件):改变文件的名称或name,封装的命令是mv,成功返回0,失败返回-1并设置errno
mkdir(目录名称,权限):创建一个目录文件,注意umask值会影响权限,成功返回0,失败返回-1并设置errno
rmdir(目录名称):删除一个目录文件,必须是空目录
getcwd(缓存,缓存大小):获取到当前的工作路径,填充到缓存中,
成功返回一个指针指向当前工作路径的字符串,失败返回NULL,并设置errno
#define BUFSIZE 1024
int main(void)
{
char buf[BUFSIZE];
getcwd(buf,BUFSIZE); //获取当前工作目录的据对路径
puts(buf);
exit(0);
}
glob(pattern,特殊要求,函数指针,回填结构体):
//读取当前目录文件到glb 结构体中
参数一:要解析的路径,可以带通赔符
参数二:需要多个特殊要求就使用按位或的形式进行传参
特殊要求:
GLOB_NOCHECK:如果没有匹配上正确与指定的pattern相等的字符串,就直接返回pattern
GLOB_APPEND:以追加的形式存放到结构体中的argv中,注意argv中是一个随机值,第一次不要追加
参数三:错误信息的函数
参数四:解析后的数据存入到该结构体中
glob_t glb;
getpwuid(用户id):根据用户的id来获取用户的详细信息,成功获取到的数据通过返回值带出一个结构体指针,
失败返回NULL并设置errno
atoi(字符串):将一个字符串转为整数
getpwnam(用户名):根据用户的名称来获取用户的详细信息,成功获取到的数据通过返回值带出一个结构体指针,
失败返回NULL并设置errno
getgrgid(组id):根据用户组的id来获取用户组的详细信息,成功获取到的数据通过返回值带出一个结构体指针,
失败返回NULL并设置errno
getgrgnam(用户组名称):根据用户组的名称来获取用户组的详细信息,成功获取到的数据通过返回值带出一个结构体指针,
失败返回NULL并设置errno
时间戳:
time_t是一个大整型
time():从内核中获取一个时间戳,如果参数为NULL,成功返回1970-01-01 00:00:00
距离当前时间所过去的秒数,失败返回-1并设置errno
如果参数不为空,成功将值存储到参数中,返回值与参数数据相同,失败返回-1并设置errno
gmtime(时间戳):将一个时间戳转为一个tm的结构体,成功返回值为结构体指针,
失败返回值为NULL,转为格林威治时间
localtime(时间戳):将一个时间戳转为一个tm的结构,成功返回值为结构体指针,
失败返回值为NULL,转为本地时间
mktime(时间结构体):将一个时间结构体转为一个时间戳,成功返回该时间戳,失败返回-1
strftime(缓存区地址,缓存区大小,格式化字符串,时间结构体指针):格式化时间日期
练习写文件:
1 2017-1-1 10:00:00
2 2017-1-1 10:00:01
3 2017-1-1 10:00:02
4 2017-1-1 10:00:03
buf
fp = fopen("/aa");
while(1)
{
fprintf(fp,"%d %s",i,buf);
fflush(fp);
sleep(1);
}
......
注意缓存模式
2.做一个程序,先输出当前日期,再输出100天以后的日期
./myls -l
argv[0] = "./myls";
argv[1] = "-l";
argc = 2;
./myls -l /etc/pwd
./mmplayer -H1202 -W1231
命令行分析:
getopt(参数的个数argc,参数的首地址argv,遍历的选项列表):分析出命令行参数中所指定的选项,
成功返回分析出的选项字符,失败返回-1
遍历的选项列表中如果选项后带有参数可以使用冒号:
例如:
"n:ab":n代表后面会跟有一个参数,且必须跟有一个,在命令行出-n 2
"n::ab":n后面可以跟有一个参数,也可以不跟
全局变量:
optarg:当选项是带参数的,那么遍历到该选项时,optarg便指向该选项后的参数
optind:获取到当前读取到的argv的下标的下一个位置
遍历的选项中加入一个-号:遍历选项中加入一个-号代表除了可以获取到选项外,还可以获取到非选项的传参
遇到非选项的传参函数返回值为1
myls 简单实例
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <glob.h>
#include <sys/types.h>
#include <sys/stat.h>
//ls
//ls -l
#define BUFSIZE 1024
static char getflty(struct stat s)
{
if(S_ISREG(s.st_mode))
return '-';
if(S_ISDIR(s.st_mode))
return 'd';
if(S_ISCHR(s.st_mode))
return 'c';
if(S_ISBLK(s.st_mode))
return 'b';
if(S_ISFIFO(s.st_mode))
return 'p';
if(S_ISLNK(s.st_mode))
return 'l';
if(S_ISSOCK(s.st_mode))
return 's';
}
char *getquanxian(struct stat s)
{
//char arr[10];
char *arr = malloc(10);
arr[0] = s.st_mode & S_IRUSR ? 'r':'-';
arr[1] = s.st_mode & S_IWUSR ? 'w':'-';
arr[2] = s.st_mode & S_IXUSR ? 'x':'-';
arr[3] = s.st_mode & S_IRGRP ? 'r':'-';
arr[4] = s.st_mode & S_IWGRP ? 'w':'-';
arr[5] = s.st_mode & S_IXGRP ? 'x':'-';
arr[6] = s.st_mode & S_IROTH ? 'r':'-';
arr[7] = s.st_mode & S_IWOTH ? 'w':'-';
arr[8] = s.st_mode & S_IXOTH ? 'x':'-';
arr[9] = '\0';
return arr;
}
int main(int argc,char **argv)
{
int res;
char buf[BUFSIZE];
glob_t glb;
int i;
struct stat sta;
while(1)
{
res = getopt(argc,argv,"l");//分析出命令行参数中所指定的选项,
//成功返回分析出的选项字符,失败返回-1
if(res < 0)
break;
switch(res)
{
case 'l':
getcwd(buf,BUFSIZE);//读取当前绝对路径地址
printf("%s",buf);
strcat(buf,"/*");// 添加在buf 末尾/*
printf("%s",buf);
glob(buf,0,NULL,&glb);//读取当前目录文件到glb 结构体中
for(i = 0 ; i < glb.gl_pathc; i++)
{
stat(glb.gl_pathv[i],&sta);
printf("%c%s\n",getflty(sta),getquanxian(sta));
}
break;
}
}
exit(0);
}
结果:
实现一个mydate:
要求:./mydate
输出:2017-10-11 10:00:00
./mydate -y
输出:2017
字符串分割:
strtok(要分割的字符串,分隔符):将一个字符串根据分割符分割成若干个子串,
每次返回一个子串,返回NULL代表分割结束
注意:在循环分割的过程中需要将参数1(要分割的字符串)制NULL
int main(void)
{
char arr[] = "192.168.1.123";
char *ptr = arr;
char *p = NULL;
while(1)
{
p = strtok(ptr,".");
if(p == NULL)
break;
puts(p);
ptr = NULL;
}
exit(0);
}
strsep(要分割的字符串的地址,分割符):根据分割符将第一个参数分割成若干子串,
返回值为每一个子串的首地址,返回NULL代表分割结束
int main(void)
{
char arr[] = "/bin/linux/pwd";
char *ptr = arr;
char *res = NULL;
while(1)
{
res =strsep(&ptr,"/");
if(res == NULL)
break;
puts(res);
}
exit(0);
}