继上一篇UNIX/Linux文件和目录操作(一)继续来讲文件和目录操作函数。
1、chdir/fchdir/getcwd函数
头文件
#include <unistd.h>
int chdir(const char *path);
功能:修改进程的工作目录
返回值:0 成功,-1 失败
int fchdir(int fd);
功能:修改进程的工作目录
fd:被open函数打开的文件目录fd
char *getcwd(char *buf, size_t size);
功能:获取当前进程的工作目录,工作目录是指当不加路径信息时,创建/打开文件时从那个目录下查找,工作目录默认是程序所在的目录
buf:缓冲区地址
size:缓冲区的长度(以字节为单位)
注意:缓冲区必须有足够的长度以容纳绝对路径名再加上一个终止NULL字节,否则返回出错。
2、opendir/fdopendir/closedir/readdir/rewinddir/telldir/seekdir函数
头文件
#include <sys/types.h>
#include <dirent.h>
DIR *opendir(const char *name);
功能:打开一个目录流
返回值:目录流(即链表)
DIR *fdopendir(int fd);
功能:使用文件描述符获取目录流
fd:必须是目录文件的文件描述符
int closedir(DIR *dirp);
功能:关闭目录流
头文件
#include <dirent.h>
struct dirent *readdir(DIR *dirp)
功能:从目录流中读取一个文件节点信息
接着就是dirent结构体,它不仅指向目录,还指向目录的具体文件,以下为dirent结构体的定义:
struct dirent
{
long d_ino; /* inode number 索引节点号 */
off_t d_off; /* offset to this dirent 在目录文件中的偏移 */
unsigned short d_reclen; /* length of this d_name 文件名长 */
unsigned char d_type; /* the type of d_name 文件类型 */
char d_name [NAME_MAX+1]; /* file name (null-terminated) 文件名,最长255字符 */
}
从上述定义也能够看出来,dirent结构体存储的关于文件的信息很少,所以dirent同样也是起着一个索引的作用,如果想获得类似ls -l那种效果的文件信息,必须要靠stat函数了。
d_type
表示档案类型
enum
{
DT_UNKNOWN = 0, //未知类型
# define DT_UNKNOWN DT_UNKNOWN
DT_FIFO = 1, //管道
# define DT_FIFO DT_FIFO
DT_CHR = 2, //字符设备
# define DT_CHR DT_CHR
DT_DIR = 4, //目录
# define DT_DIR DT_DIR
DT_BLK = 6, //块设备
# define DT_BLK DT_BLK
DT_REG = 8, //常规文件
# define DT_REG DT_REG
DT_LNK = 10, //符号链接
# define DT_LNK DT_LNK
DT_SOCK = 12, //套接字
# define DT_SOCK DT_SOCK
DT_WHT = 14 //链接
# define DT_WHT DT_WHT
};
头文件
#include <sys/types.h>
#include <dirent.h>
void rewinddir(DIR *dirp);
功能:把目录流的位置指针调整到开头
long telldir(DIR *dirp);
功能:获取当前目录的位置指针在第几个文件节点
void seekdir(DIR *dirp, long offset);
功能:调整当前目录流的位置指针
offset:根据开头位置指针进行偏移
struct passwd *getpwuid(uid_t uid);
功能:根据用户ID获取用户名
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 */
};
struct group *getgrgid(gid_t gid);
功能:根据组ID获取组名
struct group {
char *gr_name; /* group name */
char *gr_passwd; /* group password */
gid_t gr_gid; /* group ID */
char **gr_mem; /* group members */
};
以上差不多就是关于UNIX文件和目录的的主要函数,对文件和目录的所有属性以及对文件和目录进行操作的所有函数的全面了解,对于UNIX编程是非常重要的。
下面看一个实例:
实现 ls -l 的功能
#include <stdio.h>
#include<stdlib.h>
#include <string.h>
#include <unistd.h>
#include <dirent.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <time.h>
#include <pwd.h>
#include <grp.h>
void show_name(char* name,char* info)
{
printf("%s",info);
if('d' == info[0])
{
printf("\33[1;34m %s\n\033[0m",name);
}
else if('x' == info[3])
{
printf("\33[1;32m %s\n\033[0m",name);
}
else
{
printf(" %s\n",name);
}
}
char* file_time(time_t t,char* str)
{
struct tm* it = localtime(&t);
sprintf(str,"%s %2d月 %02d %02d:%02d",str,it->tm_mon+1,it->tm_mday,it->tm_hour,it->tm_min);
return str;
}
char* id_to_user(uid_t uid,char* str)
{
struct passwd* pd = getpwuid(uid);
sprintf(str,"%s %s",str,pd->pw_name);
return str;
}
char* id_to_group(gid_t gid,char* str)
{
struct group* gp = getgrgid(gid);
sprintf(str,"%s %s",str,gp->gr_name);
return str;
}
char* dir_cnt(char* name,char* str)
{
int cnt = 1;
if('d' == str[0])
{
cnt = 0;
char arr[255] = {};
DIR* dp = opendir(name);
if(NULL == dp)
{
perror("opendir");
return str;
}
for(struct dirent* de=readdir(dp); NULL!=de;de=readdir(dp))
{
if(DT_DIR == de->d_type)
{
cnt++;
}
}
}
sprintf(str,"%s %d",str,cnt);
return str;
}
char* file_mode(mode_t m,char* str)
{
if(S_ISREG(m))
str[0] = '-';
else if(S_ISDIR(m))
str[0] = 'd';
else if(S_ISCHR(m))
str[0] = 'c';
else if(S_ISBLK(m))
str[0] = 'b';
else if(S_ISFIFO(m))
str[0] = 'q';
else if(S_ISLNK(m))
str[0] = 'l';
else if(S_ISSOCK(m))
str[0] = 's';
else
str[0] = '?';
str[1] = '\0';
strcat(str,S_IRUSR&m?"r":"-");
strcat(str,S_IWUSR&m?"w":"-");
strcat(str,S_IXUSR&m?"x":"-");
strcat(str,S_IRGRP&m?"r":"-");
strcat(str,S_IWGRP&m?"w":"-");
strcat(str,S_IXGRP&m?"x":"-");
strcat(str,S_IROTH&m?"r":"-");
strcat(str,S_IWOTH&m?"w":"-");
strcat(str,S_IXOTH&m?"x":"-");
return str;
}
void list_file(const char* path)
{
DIR* dp = opendir(path);
if(NULL == dp)
{
perror("opendir");
return;
}
char info[80] = {};
for(struct dirent* de=readdir(dp); NULL!=de;
de=readdir(dp))
{
if('.' == de->d_name[0]) continue;
struct stat buf = {};
if(stat(de->d_name,&buf))
{
perror("stat");
return;
}
file_mode(buf.st_mode,info);
dir_cnt(de->d_name,info);
id_to_user(buf.st_uid,info);
id_to_group(buf.st_gid,info);
sprintf(info,"%s %5lu",info,buf.st_size);
file_time(buf.st_mtime,info);
show_name(de->d_name,info);
}
}
int main(int argc,char* argv[])
{
if(argc == 2)
{
if(0 == strcmp("-l",argv[1]))
list_file(".");
}
else if(argc == 3)
{
if(0 == strcmp("-l",argv[1]))
list_file(argv[2]);
}
else
{
printf("User:ls -l xxx\n");
}
}
实现效果:
$:gcc task1.c -o ls
$:ls -l
总用量 64
-rwxrwxr-x 1 zhizhen zhizhen 11883 8月 9 09:13 a.out
-rwxrwx--- 1 zhizhen zhizhen 133 7月 29 11:10 dome1.c
-rwxrwx--- 1 zhizhen zhizhen 523 7月 29 12:30 dome2.c
-rwxrwx--- 1 zhizhen zhizhen 409 7月 29 14:51 dome3.c
-rwxrwx--- 1 zhizhen zhizhen 172 7月 29 14:52 dome4.c
-rwxrwx--- 1 zhizhen zhizhen 270 7月 29 15:00 dome5.c
-rwxrwx--- 1 zhizhen zhizhen 195 7月 29 15:07 dome6.c
-rwxrwx--- 1 zhizhen zhizhen 311 7月 29 15:37 dome7.c
-rwxrwx--- 1 zhizhen zhizhen 932 7月 29 16:16 dome8.c
-rwxrwx--- 1 zhizhen zhizhen 5659 7月 29 16:30 note.c
-rwxrwx--- 1 zhizhen zhizhen 2637 8月 9 09:14 task1.c
-rwxrwx--- 1 zhizhen zhizhen 489 7月 29 10:31 task2.c
-rwxrwx--- 1 zhizhen zhizhen 45 7月 29 10:47 test.c