对于linux
文件目录操作函数其实使用命令就能实现,但是其实对于一些命令本质上就是调用系统函数的,比如:madir
,umask
,chown
等命令。
#include
#include
#include
//不能读取软连接文件
int stat(const char *path, struct stat *buf);
//根据文件描述符读取文件信息
int fstat(int fd, struct stat *buf);
//能读取软连接文件,stat对于软连接,读取到的信息为指向的目标对象
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(m)
判断文件是否为普通文件,,参数m
为结构体中的st_mode
成员,若m
为宏功能所指对象,则返回真值,不符合为假
- S_ISDIR(m) 判断文件是否为目录文件
- S_ISCHR(m) 判断文件是否为字符文件
- S_ISBLK(m) 判断文件是否为块文件
- S_ISFIFO(m) 判断文件是否为管道文件
- S_ISLNK(m) 判断文件是否为符号链接文件
- S_ISSOCK(m) 判断文件是否为套接字文件
其中
st_mode
也包含文件的访问权限位,每个文件(包括目录)都有九个访问权限位,如下:
- S_IRUSR(m) 用户读权限
- S_IWUSR(m) 用户写权限
- S_IXUSR(m) 用户可执行权限
- S_IRWXU(m) 用户读权限,用户写权限,用户可执行权限
- S_IRGRP(m) 同组读权限
- S_IWGRP(m) 同组读权限
- S_IXGRP(m) 同组可执行权限
- S_IRWXG(m) 同组读权限,同组读权限,同组可执行权限
- S_IROTH(m) 其他读权限
- S_IWOTH(m) 其他写权限
- S_IXOTH(m) 其他可执行权限
- S_IRWXO(m) 其他读权限,其他写权限,其他可执行权限
函数举例应用
#include
#include
#include
#include
int main(int argc,char *argv[])
{
struct stat st;
int i;
for(i=1; iif( 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;
}
程序运行效果:
root@DESKTOP-FR31BP0:/mnt/e/linuxcode/c/stat# make
gcc -o stat stat.c
root@DESKTOP-FR31BP0:/mnt/e/linuxcode/c/stat# ./stat /tmp
direct file
root@DESKTOP-FR31BP0:/mnt/e/linuxcode/c/stat# ./stat ./stat.c
regular file
root@DESKTOP-FR31BP0:/mnt/e/linuxcode/c/stat#
我们都知道在linux
下创建一个文件或者目录之后是可以通过chmod
等命令进行权限设置,来达到给当前用户、用户组用户以及其他用户分配不同的访问权限。那么,我们新创建的目录和文件本身也是有它的默认权限的,这个默认权限是什么,就是由权限掩码umask
所确定的。它的功能可以说与chmod
刚好相反的,代表默认拿走的也就是说不要的权限。
函数结构:
#include
#include
mode_t umask(mode_t mask);
函数参数:
- mask
由刚才所讲的十二个文件访问权限按位或构成的,也可以为一个四位整数,如0777
,文件什么权限都没有,0000
具有全部权限。- 返回值
总是成功,没有返回失败的参数,返回值总是当前umask
的值。
函数应用举例:
#include
#include
#include
#include
#include
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;
}
#include
int chmod(const char *path, mode_t mode);
int fchmod(int fd, mode_t mode);
函数参数
- mode
同上- 返回值
成功返回0
,出错返回-1
。
函数应用举例
#include
#include
#include
#include
#include
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;
}
#include
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
#include
#include
#include
#include
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;
}
#include
#include
int mkdir(const char *pathname, mode_t mode);
参数:
- pathname
带路径的目录名称- mode
创建文件的权限,与umask
有关。应该至少要设置以为可执行权限位。这样才能访问该目录的内容。返回值
成功返回0
,失败返回-1
.
应用举例:
#include
#include
#include
#include
#include
#include
int main()
{
mkdir("./dir",0777);
return 0;
}
代码运行效果
root@DESKTOP-FR31BP0:/mnt/e/linuxcode/c/stat# make
gcc -o stat stat.c
root@DESKTOP-FR31BP0:/mnt/e/linuxcode/c/stat# ./stat
root@DESKTOP-FR31BP0:/mnt/e/linuxcode/c/stat# ls
dir Makefile stat stat.c
root@DESKTOP-FR31BP0:/mnt/e/linuxcode/c/stat# ls -l dir/
总用量 0
drwxrwxrwx 0 root root 4096 4月 18 14:46 dir
-rwxrwxrwx 1 root root 34 4月 18 14:02 Makefile
-rwxrwxrwx 1 root root 8600 4月 18 14:46 stat
-rwxrwxrwx 1 root root 196 4月 18 14:46 stat.c
root@DESKTOP-FR31BP0:/mnt/e/linuxcode/c/stat#
#include
#include
DIR *opendir(const char *name);
DIR *fdopendir(int fd);
功能
- 打开目录
参数
- name;带路径的目录名
- fd:目录ID
返回值
- DIR*形态的目录流,接下来对目录的读取和搜索都要使用此返回值,类似文件打开会返回fd,作为open,read等的索引,这里返回的是DIR指针
DIR结构体
struct __dirstream
{
void *__fd; /* `描述符的struct hurd_fd'指针 */
char *__data; /* 目录块。 */
int __entry_data; /* 条目号 */
char *__ptr; /* 当前指向该块的指针。*/
int __entry_ptr; /* 条目号 */
size_t __allocation; /* 分配给块的空间。 */
size_t __size; /* 块中的总有效数据。 */
__libc_lock_define (, __lock) /* 此结构的互斥锁。 */
};
typedef struct __dirstream DIR;
#include
struct dirent * readdir(DIR * dir);
功能
- 从指定的
drip
目录指针中获取一次当前目录中的文件信息参数
dir
要读的目录指针返回值
- 成功则返回
struct dirent
结构体指针 有错误发生或读取到目录文件尾则返回NULL
struct 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字符 */
/*
对于d_type:
DT_BLK:块设备
DT_CHR:字符设备
DT_DIR:目录
DT_LNK:软连接
DT_FIFO:管道
DT_REG:普通文件
DT_SOCK:套接字文件
DT_UNKNOWN:未知
*/
}
#include
#include
int closedir(DIR *dirp);
功能
- 关闭目录
参数
- dirp:目录的描述指针
返回值
关闭成功则返回
0
,,失败返回-1
,,错误原因存于errno
#include
int remove(const char *pathname);
功能
- 删除指定路径的文件或目录
参数
pathname
:文件名或目录路径,filename
为要删除的文件名,也可以为一目录。如果参数filename
为一文件,则调用unlink()
处理;若参数filename
为目录,则调用rmdir()
来处理,且该目录必须为空。返回值
- 成功则返回
0
,失败则返回-1
,错误原因存于errno
补充
int rmdir(const char *pathname); //使用rmdir()函数时,目录必须为空,否则调用失败,函数返回-1.成功时,函数返回0 int unlink(const char *pathname);
#include
#include
#include
#include
#include
int get_file_num(char *root)
{
int total=0;
DIR* dir=NULL;
struct dirent* dirent;
dir=opendir(root);
if(dir==NULL)
{
perror("opendir");
exit(1);
}
while((dirent=readdir(dir))!=NULL)
{
if( (strcmp(".",dirent->d_name)==0 || strcmp("..",dirent->d_name)==0) )
{
continue;
}
if( dirent->d_type == DT_REG )
{
total++;
printf("file name is %s\n",dirent->d_name);
}
if( dirent->d_type == DT_DIR )
{
char path[1024]={0};
sprintf(path,"%s/%s",root,dirent->d_name);
total+=get_file_num(path);
}
}
closedir(dir);
return total;
}
int main(int argc,char *argv[])
{
int sourcenum;
sourcenum = get_file_num(argv[1]);
printf("file num is %d\n",sourcenum);
return 0;
}
程序运行效果:
root@thinkpad:/zhang/codefiles# ./a.out /root
file name is .bashrc
file name is accels
file name is user
file name is .viminfo
file name is recently-used.xbel
file name is .bash_history
file name is 9d35ab44d48248f2a61cf41d713e89a2-0
file name is .vimrc
file name is .profile
file num is 9
root@thinkpad:/zhang/codefiles# ls /root/ -a
. .. .bash_history .bashrc .cache .config .dbus .local .profile .viminfo .vimrc
root@thinkpad:/zhang/codefiles#