对于linux文件目录操作函数其实使用命令就能实现,但是其实对于一些命令本质上就是调用系统函数的,比如:madir,umask,chown等命令。所以此篇博客就对文件目录操作的系统函数进行一下总结。
(1)stat,fstat,fstatat 获取文件信息
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
int stat(const char *path, struct stat *buf);
int fstat(int fd, struct stat *buf);
int lstat(const char *path, struct stat *buf);
- path: 文件的路径,即文件名称。
buf: 存储文件信息的一个结构体指针,形式如下:
struct stat { dev_t st_dev; //device 文件的设备编号 ino_t st_ino; //inode 文件的i-node mode_t st_mode; //protection 文件的类型和存取的权限 nlink_t st_nlink; //number of hard links 连到该文件的硬连接数目, 刚建立的文件值为1. uid_t st_uid; //user ID of owner 文件所有者的用户识别码 gid_t st_gid; //group ID of owner 文件所有者的组识别码 dev_t st_rdev; //device type 若此文件为装置设备文件, 则为其设备编号 off_t st_size; //total size, in bytes 文件大小, 以字节计算 unsigned long st_blksize; //blocksize for filesystem I/O 文件系统的I/O 缓冲区大小. unsigned long st_blocks; //number of blocks allocated 占用文件区块的个数, 每一区块大小为512 个字节. time_t st_atime; //time of lastaccess 文件最近一次被存取或被执行的时间, 一般只有在用mknod、utime、read、write 与tructate 时改变. time_t st_mtime; //time of last modification 文件最后一次被修改的时间, 一般只有在用mknod、utime 和write 时才会改变 time_t st_ctime; //time of last change i-node 最近一次被更改的时间, 此参数会在文件所有者、组、权限被更改时更新 };
- 返回值:成功返回0 ,出错返回-1.
其中该函数最主要的作用之一是判断文件类型,文件类型与权限存储在st_mode中,可以用以下宏获取文件类型:
- S_ISREG 判断文件是否为普通文件
- S_ISDIR 判断文件是否为目录文件
- S_ISCHR 判断文件是否为字符文件
- S_ISBLK 判断文件是否为块文件
- S_ISFIFO 判断文件是否为管道文件
- S_ISLNK 判断文件是否为符号链接文件
- S_ISSOCK 判断文件是否为套接字文件
其中st_mode也包含文件的访问权限位,每个文件(包括目录)都有九个访问权限位,如下:
- S_IRUSR 用户读权限
- S_IWUSR 用户写权限
- S_IXUSR 用户可执行权限
- S_IRWXU 用户读权限,用户写权限,用户可执行权限
- S_IRGRP 同组读权限
- S_IWGRP 同组读权限
- S_IXGRP 同组可执行权限
- S_IRWXG同组读权限,同组读权限,同组可执行权限
- S_IROTH 其他读权限
- S_IWOTH 其他写权限
- S_IXOTH 其他可执行权限
- S_IRWXO 其他读权限,其他写权限,其他可执行权限
例如:
#include <stdio.h>
#include <unistd.h>
#include <sys/stat.h>
#include <stdlib.h>
int main(int argc,char *argv[])
{
struct stat st;
int i;
for(i=1; i<argc; i++)
{
if( stat(argv[i],&st) == -1 )
{
perror("stat fail\n");
exit(EXIT_FAILURE);
}
if( S_ISREG(st.st_mode) )
{
printf("regular file\n");
}
else if (S_ISDIR(st.st_mode) )
{
printf("direct file\n");
}
else if( S_ISCHR(st.st_mode) )
{
printf("char file\n");
}
else if( S_ISBLK(st.st_mode) )
{
printf("block fil\n");
}
else
{
printf("noknw file\n");
}
}
return 0;
}
(2)umask 为进程设置文件模式创建屏蔽字,简单的将该函数可以指定创建文件的权限。
#include <sys/types.h>
#include <sys/stat.h>
- mask :由刚才所讲的十二个文件访问权限按位或构成的,也可以为一个四位整数,如0777,文件什么权限都没有,0000具有全部权限。
- 返回值:总是成功,没有返回失败的参数,返回值总是当前umask的值。
例如:
#include <stdio.h>
#include <unistd.h>
#include <sys/stat.h>
#include <stdlib.h>
#include <fcntl.h>
int main()
{
umask(0);
if( creat("a.txt",S_IRWXU|S_IRWXG) == -1 )
{
perror("create fail\n");
exit(EXIT_FAILURE);
}
umask(0777);//此时创建的文件什么权限都没有
system("touch bbbb");
if( creat("b.txt",S_IRWXO|S_IRWXU) == -1 )
{
exit(EXIT_FAILURE);
}
return 0;
}
(3)chmod,fchmod,改变文件权限
#include <sys/stat.h>
int chmod(const char *path, mode_t mode);
int fchmod(int fd, mode_t mode);
- mode 同上
- 返回值:成功返回0 ,出错返回-1.
例如:
#include <stdio.h>
#include <fcntl.h>
#include <sys/types.h>
#include <stdlib.h>
#include <unistd.h>
int main(int argc,char * argv[])
{
struct stat st;
if( stat(argv[1],&st) == -1 )
{
perror("stat fail\n");
exit(EXIT_FAILURE);
}
system("ls -l ji");
chmod(argv[1],st.st_mode | S_IXOTH );
system("ls -l ji");
chmod(argv[1],st.st_mode&(~S_IWUSR));
system("ls -l ji");
return 0;
}
(4)chown,fchown,改变文件用户ID与组ID
#include <unistd.h>
int chown(const char *path, uid_t owner, gid_t group);
int fchown(int fd, uid_t owner, gid_t group);
int lchown(const char *path, uid_t owner, gid_t group);
例如:
//只有超级用户才能进行更改文件所属人
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/stat.h>
#include <fcntl.h>
int main(int argc,char * argv[])
{
struct stat st;
if( stat(argv[1],&st) == -1 )
{
perror("stat fail\n");
exit(EXIT_FAILURE);
}
printf("uid:%d,gid:%d\n",st.st_uid,st.st_gid);
system("ls -l ji");
chown(argv[1],(uid_t)0,(gid_t)0);
stat(argv[1],&st);
printf("uid:%d,gid:%d\n",st.st_uid,st.st_gid);
system("ls -l ji");
return 0;
}
(5)truncate,截断文件至指定长度。
#include <unistd.h>
#include <sys/types.h>
int truncate(const char *path, off_t length);
int ftruncate(int fd, off_t length);
- 返回值:成功返回0 ,出错返回-1.
例如:
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <fcntl.h>
#include <stdlib.h>
int main(int argc,char * argv[])
{
system("ls -l ji");
if( truncate(argv[1],20) == -1 )
{
perror("truncate err\n");
exit(EXIT_FAILURE);
}
system("ls -l ji");
return 0;
}
(6)link
#include <unistd.h>
- oldpath : 源文件名
- newpath :新的连接文件名
- 返回值:成功返回0 ,出错返回-1.
例如:
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
int main(int argc,char * argv[])
{
if( access(argv[1],F_OK) == -1 )
{
perror("file not exit!\n");
exit(EXIT_FAILURE);
}
if( link(argv[1],"newfile") == -1 )
{
perror("create link err\n");
exit(EXIT_FAILURE);
}
return 0;
}
(7)mkdir,创建新的目录
#include <sys/stat.h>
#include <sys/types.h>
int mkdir(const char *pathname, mode_t mode);
- pathname: 要创建的目录名称。
- mode : 创建文件的权限,与umask有关。应该至少要设置以为可执行权限位。这样才能访问该目录的内容。
- 返回值: 成功返回0 ,失败返回-1.
(8)opendir,打开目录
#include <sys/types.h>
#include <dirent.h>
DIR *opendir(const char *name);
- 其中返回值是一个DIR类型的指针。若失败返回NULL.
(9)readdir 读取该目录文件中的文件
#include <dirent.h>
struct dirent *readdir(DIR *dirp);
- 返回struct dirent类型的指针。
例如:
#include <stdio.h>
#include <time.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdlib.h>
#include <dirent.h>
#include <sys/types.h>
int main(int argc,char *argv[])
{
DIR * dp = NULL;
struct stat st;
struct dirent *dirp = NULL;
if( (dp = opendir(argv[1])) == NULL)
{
perror("opendir err\n");
exit(EXIT_FAILURE);
}
while( (dirp = readdir(dp)) != NULL )
{
if( stat(dirp->d_name,&st) == -1 )
{
perror("stat err\n");
exit(EXIT_FAILURE);
}
printf("%d %12d %12d %12d %20s\ %12s \n",st.st_nlink,st.st_uid,st.st_gid,st.st_size,asctime(localtime(&(st.st_ctime))),dirp->d_name);
}
return 0;
}
(9)unlink,如果文件连接数为1,则直接删除该文件,如果大于1,则删除该文件名,并使得该文件的连接数减去1.
#include <unistd.h>
int unlink(const char *pathname);
- 返回值: 成功返回0 ,否者返回 -1.
例如:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
int main(int argc,char * argv[])
{
if( unlink(argv[1]) < 0)
{
printf("unlink err\n");
exit(EXIT_FAILURE);
}
return 0;
}
(10)chdir,改变当前进程的当前工作目录,只影响该进程。
#include <unistd.h>
int chdir(const char *path);
int fchdir(int fd);
- 返回值: 成功返回0 ,否者返回 -1。
(11)getcwd ,由于内核只为每个进程保存该目录的v节点的指针,等目录本身的信息,而不不保存目录的完整路径,所有要想获得当前进程的完整路径,需要用getcwd函数。
#include <unistd.h>
char *getcwd(char *buf, size_t size);
char *get_current_dir_name(void);//获得当前路径
- buf :用于存放完整路径名的数组
- size:该数组的长度。该长度必须能容纳完整路径名长度加1,加一因为最后有个null字符。
- 返回值: 成功返回buf指针,否则返回NULL.
例如:
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#define SIZE 100
int main(int argc,char * argv[])
{
char buff[SIZE];
if( getcwd(buff,SIZE) == NULL )
{
perror("getced err\n");
exit(EXIT_FAILURE);
}
printf("%s\n",buff);
printf("%s\n",get_current_dir_name());
return 0;
}
好了。对于目录的操作也就总结完了,虽然只是进行了简单的对每个函数进行讲解,但感觉还是受益匪浅,特别是基本上每个函数都有一个例子,清晰的表明函数了函数的用法。