改变目录或文件的访问权限:
#include <sys/stat.h>
int chmod(const char* path, mode_t mode);
//path 参数指定的文件被修改为具有 mode 参数给出的访问权限
获取、改变当前目录:
#include <unistd.h> //头文件
char *getcwd(char *buf, size_t size); //获取当前目录,相当于 pwd 命令
int chdir(const char *path); //修改当前目录,即切换目录,相当于 cd 命令
getcwd()函数: 将当前的工作目录绝对路径复制到参数 buf 所指的内存空间, 参数 size 为 buf
的空间大小。倘若参数 buf 为 NULL,getcwd()会依参数 size 的大小自动配置内存(使用malloc()),如果参数 size 也为 0,则 getcwd()会 依工作目录绝对路径的字符串程度来决定所配置的内存大小,进程可以在使用完此字符串后自动利用 free()来释放此空间。所以常用的形式:getcwd(NULL, 0)。
chdir()函数:用来将当前的工作目录改变成以参数 path 所指的目录。
#include<unistd.h>
int main()
{
chdir(“/tmp”);
printf(“current working directory: %s\n”,getcwd(NULL,0));
return 0;
}
创建和删除目录:
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
int mkdir(const char *pathname, mode_t mode); //创建目录,mode 是目录权限
int rmdir(const char *pathname); //删除目录
获取目录信息:
#include <sys/types.h>
#include <dirent.h>
DIR *opendir(const char *name); //打开一个目录
struct dirent *readdir(DIR *dir); //读取目录的一项信息,并返回该项信息的结构体指针
void rewinddir(DIR *dir); //重新定位到目录文件的头部
void seekdir(DIR *dir,off_t offset); //用来设置目录流目前的读取位置
off_t telldir(DIR *dir); //返回目录流当前的读取位置
int closedir(DIR *dir); //关闭目录文件
seekdir()用来设置参数dir目录流读取位置,在调用readdir()时便从此新位置开始读取。参数offset 代表距离目录文件开头的偏移量。
读取目录信息的步骤为:
1、用 opendir 函数打开目录;
2、使用 readdir 函数迭代读取目录的内容,如果已经读取到目录末尾,又想重新开始读,则可以使用 rewinddir 函数将文件指针重新定位到目录文件的起始位置;
3、用 closedir 函数关闭目录
案例:
#include <func.h>
int main(int argc, char* argv[])
{
ARGS_CHECK(argc, 2);
DIR* dir;
dir = opendir(argv[1]);
ERROR_CHECK(dir, NULL, "opendir");
struct dirent *p;
while(p = readdir(dir))
{
printf("Ino = %ld len = %d type = %d filename = %s\n", p->d_ino, p->d_reclen, p->d_type, p->d_name);
}
closedir(dir);
return 0;
}
案例:
#include <func.h>
int main(int argc, char* argv[])
{
ARGS_CHECK(argc, 2);
DIR* dir;
dir = opendir(argv[1]); //打开一个目录,返回指向该目录流DIR的指针
ERROR_CHECK(dir, NULL, "opendir");
struct dirent *p;
off_t pos;
while(p = readdir(dir)) //读取目录的一项信息,并返回该项信息的结构体指针
{
printf("Ino = %ld len = %d type = %d filename = %s\n", p->d_ino, p->d_reclen, p->d_type, p->d_name);
if(!strcmp(p->d_name,"a.out"))
{
pos = telldir(dir); //返回目录流当前的读取位置
}
}
seekdir(dir,pos); //重新设置目录流目前的读取位置
printf("~~~~~~~~~~~~~~~~~~~~\n");
p = readdir(dir);
printf("Ino = %ld len = %d type = %d filename = %s\n", p->d_ino, p->d_reclen, p->d_type, p->d_name);
closedir(dir); //关闭目录文件
return 0;
}
DIR的结构体定义如下:
struct __dirstream {
void *__fd; /* `struct hurd_fd' pointer for descriptor. */
char *__data;
int __entry_data;
char *__ptr;
int __entry_ptr;
size_t __allocation;
size_t __size;
__libc_lock_define (, __lock)
};
typedef struct __dirstream DIR; //DIR的定义
DIR为目录流,类似于于FILE,这种文件包含了其他文件的名称和指向其他文件的文件描述符。通过opendir可以打开该目录流的接口。
opendir()用来打开参数 name 指定的目录,并返回 DIR*形态的目录流,和文件操作函数 open()类
似,接下来对目录的读取和搜索都要使用此返回值。函数失败则返回 NULL。
readdir()函数用来读取目录的信息,并返回一个结构体指针,该指针保存了目录的相关信息。有
错误发生或者读取到目录文件尾则返回 NULL。
struct dirent
{
ino_t d_ino; /* inode number(此目录进入点的 inode) */
off_t d_off; /* offset to the next dirent(目录开头到进入点的位移) */
unsigned short d_reclen; /* length of this record(目录名的长度) */
unsigned char d_type; /* type of file(所指的文件类型) */
char d_name[256]; /* filename(文件名) */
};
所有的dirent信息构成的链表(顺序表)为DIR,存在一个指针定位当前所在的链表结点。
每次readdir会移动到链表的下一结点,readdir读取信息后,指针向后偏移,d_off指的是下一个结点的位置。经常用seekdir回到某个位置,而用telldir记录一个位置。
seekdir()函数用来设置目录流目前的读取位置,再调用 readdir()函数时,便可以从此新位置开始
读取。参数 offset 代表距离目录文件开头的偏移量。
telldir()函数用来返回目录流当前的读取位置。
获取文件信息
可以通过 fstat 和 stat 函数获取文件信息,调用完毕后,文件信息被填充到结构体 struct stat
变量中,函数原型为:
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
int stat(const char *file_name, struct stat *buf); //文件名 stat 结构体指针
int fstat(int fd, struct stat *buf); //文件描述符 stat 结构体指针
结构体 stat 的定义为:
struct stat {
dev_t st_dev; /*如果是设备,返回设备表述符,否则为 0*/
ino_t st_ino; /* i 节点号 */
mode_t st_mode; /* 文件类型 */ 无符号短整型
nlink_t st_nlink; /* 链接数 */
uid_t st_uid; /* 属主 ID */
gid_t st_gid; /* 组 ID */
dev_t st_rdev; /* 设备类型*/
off_t st_size; /* 文件大小,字节表示 */
blksize_t st_blksize; /* 块大小*/
blkcnt_t st_blocks; /* 块数 */
time_t st_atime; /* 最后访问时间*/
time_t st_mtime; /* 最后修改时间*/
time_t st_ctime; /* 最后权限修改时间 */
};
对于结构体的成员 st_mode,有一组宏可以进行文件类型的判断:
S_ISLNK(mode) 判断是否是符号链接
S_ISREG(mode) 判断是否是普通文件
S_ISDIR(mode) 判断是否是目录
S_ISCHR(mode) 判断是否是字符型设备
S_ISBLK(mode) 判断是否是块设备
S_ISFIFO(mode) 判断是否是命名管道
S_ISSOCK(mode) 判断是否是套接字
案例:
#include<sys/stat.h>
#include<unistd.h>
int main()
{
struct stat buf;
stat (“/etc/passwd”,&buf);
printf(“/etc/passwd file size = %d \n”,buf.st_size);//st_size 可以得到文件大小
return 0;
}
//如果用 fstat 函数实现,如下:
int fd = open (“/etc/passwd”,O_RDONLY); //先获得文件描述符
fstat(fd, &buf);
案例:以树形结构的形式输出指定目录下面的所有文件
#include <func.h> //自定义的头文件
int printDir(char *path, int width)
{
DIR* dir;
dir = opendir(path);
ERROR_CHECK(dir, NULL, "opendir"); //自定义的宏
struct dirent *p;
char buf[1024]={0};
while(p = readdir(dir))
{
if (!strcmp(p->d_name, ".")||!strcmp(p->d_name, ".."))
{
continue;
}
printf("%*s%s\n",width,"",p->d_name);
sprintf(buf,"%s%s%s",path,"/",p->d_name);
if(4 == p->d_type)
{
printDir(buf, width+4);
}
}
closedir(dir);
}
int main(int argc, char* argv[])
{
ARGS_CHECK(argc, 2); //自定义的宏
puts(argv[1]);
printDir(argv[1], 4);
return 0;
}
案例:传递任意一个目录路径,能够显示该目录的ls -l的效果
#include <func.h>
void printState(char* argv)
{
int ret;
struct stat buf;
ret = stat(argv,&buf); //传出参数
//打印文件类型
char file_type = '0';
if(S_ISLNK(buf.st_mode)) file_type = 'l';
else if( S_ISREG(buf.st_mode) ) file_type = '-';
else if( S_ISDIR(buf.st_mode) ) file_type = 'd';
else if( S_ISCHR(buf.st_mode) ) file_type = 'c';
else if( S_ISBLK(buf.st_mode) ) file_type = 'b';
else if( S_ISFIFO(buf.st_mode) ) file_type = 'p';
else if( S_ISSOCK(buf.st_mode) ) file_type = 's';
printf("%c ",file_type);
//打印文件权限
char buffer[10]={0};
char tmp_buf[] = "rwxrwxrwx";
for(int i=0;i<9;i++)
{
if(buf.st_mode & (1<<(8-i)))
{
buffer[i] = tmp_buf[i];
}
else
{
buffer[i] = '-';
}
}
printf("%s",buffer);
printf("%ld %s %s %ld %s ",buf.st_nlink,getpwuid(buf.st_uid)->pw_name,getgrgid(buf.st_gid)->gr_name
,buf.st_size,ctime(&buf.st_mtime));
}
int printDir(char *path)
{
DIR* dir;
dir = opendir(path);
ERROR_CHECK(dir, NULL, "opendir");
struct dirent *p;
char buf[1024]={0};
// char buf_t[1024]={0};
while(p = readdir(dir))
{
if (!strcmp(p->d_name, ".")||!strcmp(p->d_name, ".."))
{
continue;
}
sprintf(buf,"%s%s%s",path,"/",p->d_name);
char *argv = buf;
printState(argv);
printf("%s\n",p->d_name);
// sprintf(buf,"%s%s%s",path,"/",p->d_name);
if(4 == p->d_type)
{
printDir(buf);
}
}
closedir(dir);
}
int main(int argc, char* argv[])
{
ARGS_CHECK(argc, 2);
printDir(argv[1]);
return 0;
}