UNIX/Linux文件和目录操作(二)

  继上一篇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  89 09:13 a.out
-rwxrwx--- 1 zhizhen zhizhen   133  729 11:10 dome1.c
-rwxrwx--- 1 zhizhen zhizhen   523  729 12:30 dome2.c
-rwxrwx--- 1 zhizhen zhizhen   409  729 14:51 dome3.c
-rwxrwx--- 1 zhizhen zhizhen   172  729 14:52 dome4.c
-rwxrwx--- 1 zhizhen zhizhen   270  729 15:00 dome5.c
-rwxrwx--- 1 zhizhen zhizhen   195  729 15:07 dome6.c
-rwxrwx--- 1 zhizhen zhizhen   311  729 15:37 dome7.c
-rwxrwx--- 1 zhizhen zhizhen   932  729 16:16 dome8.c
-rwxrwx--- 1 zhizhen zhizhen  5659  729 16:30 note.c
-rwxrwx--- 1 zhizhen zhizhen  2637  89 09:14 task1.c
-rwxrwx--- 1 zhizhen zhizhen   489  729 10:31 task2.c
-rwxrwx--- 1 zhizhen zhizhen    45  729 10:47 test.c

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值