一、目录操作函数
opendir 打开目录
readdir 读目录文件
closedir 关闭目录
chdir 修改当前所处路径
1、打开目录:opendir
#include <sys/types.h>
#include <dirent.h>
DIR *opendir(const char *name);
功能:打开目录文件
参数:name:文件名
返回值:成功返回目录流指针,失败NULL,更新error
2、closedir 关闭目录2
#include <sys/types.h>
#include <dirent.h>
int closedir(DIR *dirp);
功能:关闭目录
参数:dirp:目录流指针
返回值:成功0,失败-1,更新errno
3、readdir 读目录文件
#include <sys/types.h>
#include <dirent.h>
struct dirent *readdir(DIR *dirp);
功能:读目录文件
参数:dirp:目录流指针
返回值:成功返回结构体指针,读到文件结尾返回NULL
失败NULL,更新errno
struct dirent
{
ino_t d_ino; /*文件的inode */
off_t d_off; /* not an offset; see NOTES */
unsigned short d_reclen; /* 记录的长度 */
unsigned char d_type; /* 文件类型,并不支持所有文件类型*/
char d_name[256]; /* filename */
}
练习实现ls功能
#include<stdio.h>
#include <sys/types.h>
#include <dirent.h>
int main(int argc, char const *argv[])
{
struct dirent *dir;//创建结构体
DIR *dirp = opendir(argv[1]);//打开文件
if(dirp == NULL)//容错
{
perror(" opendir err");
return -1;
}
while ((dir = readdir(dirp)) != NULL)//读取目录文件
{
if(dir->d_name[0]=='.')
continue;
printf("%s ",dir->d_name);//输出目录内容
}
puts(" ");
closedir(dirp);//关闭文件目录流
return 0;
}
4、chdir 修改当前所处路径
#include <unistd.h>
int chdir(const char *path);
功能:改变当前所处的路径
参数:path:修改的路径、
返回值:成功0
失败:-1,更新errno
二、获取文件属性函数stat
stat :显示文件或文件系统状态
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
int stat(const char *pathname, struct stat *buf);
功能:获取文件属性
参数:pathname:文件路径名
buf:保存文件属性信息的结构体
返回值:成功:0
失败:-1 更新error
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; /* 最后状态改变时间 */
};
st_mode 包含的是文件类型和权限:
文件类型:
S_IFMT 0170000 bit mask for the file type bit field
S_IFSOCK 0140000 socket-套接字 S
S_IFLNK 0120000 symbolic link-连接文件L
S_IFREG 0100000 regular file-普通文件 -
S_IFBLK 0060000 block device块设备b
S_IFDIR 0040000 directory目录 d
S_IFCHR 0020000 character 字符设备 c
S_IFIFO 0010000 FIFO管道 p
使用规则:
stat(pathname, &sb);
if ((sb.st_mode & S_IFMT) == S_IFREG) {
/* Handle regular file */
}
将使用规则封装:封装成宏函数
S_ISREG(m) is it a regular file?
S_ISDIR(m) directory?
S_ISCHR(m) character device?
S_ISBLK(m) block device?
S_ISFIFO(m) FIFO (named pipe)?
S_ISLNK(m) symbolic link? (Not in POSIX.1-1996.)
S_ISSOCK(m) socket? (Not in POSIX.1-1996.)
权限:后九位控制权限
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
1.getpwuid:通过用户id获取用户名
struct passwd *getpwuid(uid_t uid);
struct passwd
{
char *pw_name; /* username */
char *pw_passwd; /* user password */
uid_t pw_uid; /* user ID */
gid_t pw_gid; /* group ID */
char *pw_gecos; /* user information */
char *pw_dir; /* home directory */
char *pw_shell; /* shell program */
};
2.getgrgid:通过组id获取组名
struct group *getgrgid(gid_t gid);
struct group
{
char *gr_name; /* group name */
char *gr_passwd; /* group password */
gid_t gr_gid; /* group ID */
char **gr_mem; /* group members */
};
3. ctime();将时间转转换为字符串表示格式
char *ctime(const time_t *timep);
如:转换为-"Wed Jun 30 21:49:08 1993\n"
练习:用目录IO函数实现ls -l 和ls -i功能
#include<stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <pwd.h>
#include <grp.h>
#include<time.h>
#include <dirent.h>
#include<string.h>
void Show(char *file)
{
struct stat sb;
stat(file,&sb);
switch(sb.st_mode & __S_IFMT)
{
case __S_IFSOCK:printf("s");break;
case __S_IFLNK:printf("l");break;
case __S_IFREG:printf("-");break;
case __S_IFBLK:printf("b");break;
case __S_IFDIR:printf("d");break;
case __S_IFCHR:printf("c");break;
case __S_IFIFO:printf("p");break;
default:break ;
}
//法1
// char bus[3]="rwx";
// for(int i=0;i<9;i++)
// sb.st_mode & (0400>>i)?printf("%c",bus[i%3]):printf("-");
//法2
for(int i = 8;i>=0;i--)
{
if(sb.st_mode & (1<<i))
{
if(i == 8||i == 5||i == 2)
printf("r");
if(i == 7||i == 4||i == 1)
printf("w");
if(i == 6||i == 3||i == 0)
printf("x");
}
else
{
printf("-");
}
}
#if 0//法3
//用户权限
if(sb.st_mode & (1<<8))
printf("r");
else
{
printf("-");
}
if(sb.st_mode & (1<<7))
printf("w");
else
{
printf("-");
}
if(sb.st_mode & (1<<6))
printf("x");
else
{
printf("-");
}
//组用户权限
if(sb.st_mode & (1<<5))
printf("r");
else
{
printf("-");
}
if(sb.st_mode & (1<<4))
printf("w");
else
{
printf("-");
}
if(sb.st_mode & (1<<3))
printf("x");
else
{
printf("-");
}
//其他用户权限
if(sb.st_mode & (1<<2))
printf("r");
else
{
printf("-");
}
if(sb.st_mode & (1<<1))
printf("w");
else
{
printf("-");
}
if(sb.st_mode & (1<<0))
printf("x");
else
{
printf("-");
}
#endif
printf(" %u",sb.st_nlink);
struct passwd *uname = getpwuid(sb.st_uid);
struct group *gname = getgrgid(sb.st_gid);
printf(" %s",gname->gr_name);//用户名
printf(" %s",uname->pw_name);//组用户名
printf(" %ld",sb.st_size);
printf(" %.12s",4+ctime(&sb.st_mtime));
printf(" %s",file);
puts(" ");
}
int main(int argc, char const *argv[])
{
struct dirent *dir;//创建结构体
DIR *dirp = opendir("./");//打开文件
if(dirp == NULL)//容错
{
perror(" opendir err");
return -1;
}
if(!strncmp(argv[1],"-l",2))//判断输入的命令
{
while ((dir = readdir(dirp)) != NULL)//读取目录文件
{
if(dir->d_name[0]=='.')
continue;
Show(dir->d_name);
}
}
else if (!strncmp(argv[1],"-i",2))
{
struct stat sb;
stat(dir->d_name,&sb);
while ((dir = readdir(dirp)) != NULL)//读取目录文件
{
if(dir->d_name[0]=='.')
continue;
stat(dir->d_name,&sb);
printf("%-7ld",sb.st_ino);
printf("%-13s",dir->d_name);//输出目录内容
}
puts(" ");
}
closedir(dirp);//关闭文件目录流
return 0;
}