Linux下文件操作

1. Linux下文件操作的途径

(1)通过底层文件系统来实现,要求熟悉底层文件系统的结构,并且编写大量代码来完成

(2)通过调用Shell来完成,访问Shell接口,但Shell返回的信息不便于程序的分析

(3)通过系统调用来实现,能够完成相应的功能,并且返回足够的信息

2. Linux下文件操作的方式

(1)创建文件或目录
mkdir(const char* dir_path,umask);//传入的参数为路径和掩码,创建一个目录,创建成功则返回0,创建失败则返回-1
creat(const char* f_path,umask);//创建文件,创建成功则返回0,否则返回-1
open(const char* f_path,主标志,umask);//返回一个文件标识符,创建成功则返回0,否则返回-1


(2)显示文件或目录信息
fstat(int f,struct stat *buf)//第一个参数是文件描述符,第二个参数是buf指向的stat结构体指针,返回文件属性或状态信息,保存到buf指向的stat结构体指针中去
stat(const char* f_path,struct stat* buf);//第一个参数是文件路径指针变量,第二个参数是buf所指向的stat结构体变量
lstat(const char* f_path,struct stat* buf);//同上
三者区别: stat,lstat可以在文件不打开的情况下返回文件的属性或状态信息,而fstat必须在文件打开的情况下返回文件的状态或属性信息
如果是符号链接,如软链接,那么stat返回的是原来文件的属性或状态信息,而lstat返回的是符号链接的状态与属性
chdir(const char* dir_path);//切换到相应目录
chmod(const char* f_path,umask);//修改文件访问权限
DIR *opendir(const char* name);//返回一个指向DIR结构体的子目录流指针
struct dirent *readdir(DIR *dirp);//返回指向子目录流结构体中的下一个目录相关信息的结构体指针
closedir(DIR *dirp);//关闭子目录流
对目录的遍历首先返回子目录流指针,然后找子目录流的下一个目录信息,如果是下一个目录还是目录,输出目录名,则找它的子目录流指针,否则,打印文件名

(3)删除文件或目录信息
rmdir(const char* name);//文件路径,删除目录
unlink(const char* f_path);//删除文件
注意当目录中含有子目录时,不能删除,即rmdir在目录没有子目录的情况下才能运行成功

 

 

程序实例:

 

#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <dirent.h>

int creat_dir(const char* dir_path,mode_t attrib);
int creat_file(const char* f_path,mode_t attrib);
void scan_dir(const char* dir);
void delete(const char* dir);//删除创建的TestDir目录
int main(){

//首先创建一个目录 TestDir,然后创建一个子目录 subdir和一个文件file,再在这个子目录中创建一个文件file1
int f;//用于返回文件描述符
mode_t attrib;//用来保存文件的属性权限信息,mode_t是一个八进制的整数
attrib=S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH;
const char* fdir_path="TestDir";
f=creat_dir(fdir_path,attrib);
if(f==-1){
printf("%s/n","目录创建失败");
return 0;
}
else{

printf("%s/n","TestDir目录创建成功");
}
close(f);
chdir(fdir_path);//切换到TestDir目录中创建子目录
f=creat_dir("subdir",attrib);//创建子目录subdir
if(f==-1){
printf("%s/n","SubDir目录创建失败");
return 0;
}
else{

printf("%s/n","SubDir目录创建成功");
}

close(f);
f=creat_file("file",attrib);
if(f==-1){
printf("%s/n","文件file创建失败");
return 0;
}
else{

printf("%s/n","文件file创建成功");
}
close(f);
chdir("subdir");//进入subdir子目录中
f=creat_file("file1",attrib);
if(f==-1){
printf("%s/n","文件file1创建失败");
return 0;
}
else{

printf("%s/n","文件file1创建成功");
}
close(f);
chdir("..");
chdir("..");//切换到C语言程序设计目录

//下面显示TestDir的属性或状态信息
struct stat buf1;
stat(fdir_path,&buf1);
if(buf1.st_mode&S_IRUSR){
printf("%s/n","当前用户具有读文件的权限");
}
chmod(fdir_path,0771);
//遍历TestDir下的所有文件和目录
scan_dir(".");//.代表当前目录,..代表上一层目录
chdir("/home/C语言程序设计");
//删除TestDir文件操作
delete("TestDir");
rmdir("TestDir");
return 0;
}
//创建目录
int creat_dir(const char* dir_path,mode_t attrib){
return mkdir(dir_path,attrib);
}
//创建文件
int creat_file(const char* file_path,mode_t attrib){
return creat(file_path,attrib);
}

//遍历文件或目录
void scan_dir(const char* dir){
DIR *dp;//定义了一个指向子目录流的结构体指针
struct dirent *entry;//定义一个指向用于保存子目录流中下一个目录的相关属性信息的结构体指针
struct stat buf;//定义一个属性状态结构体
if((dp=opendir(dir))==NULL){

printf("%s/n","打开目录失败");
return;
}
chdir(dir);
while((entry=(readdir(dp)))!=NULL){
stat(entry->d_name,&buf);//d_name是dirent结构体中的目录名
if(buf.st_mode&S_IFDIR){//如果是目录
if(strcmp(".",entry->d_name)==0||strcmp("..",entry->d_name)==0){//如果是当前目录为空目录,则退出本次循环,找下一个目录,否则递归的进入该目录

continue;
}
printf("%s/n",entry->d_name);//打印出目录名
scan_dir(entry->d_name);
}
else{

printf("%s/n",entry->d_name);//打印出文件名
}
}
closedir(dp);
chdir("..");//退回上一层目录
}

void delete(const char* dir){
//首先扫描目录,如果有子目录扫描子目录,如果是文件,则直接删除

DIR *dp;//定义一个指向子目录流的指针
struct dirent *entry;//定义一个指向子目录流的中下一个目录的相关信息的结构体的指针
struct stat buf;//定义一个目录或文件属性或状态的结构体

if((dp=opendir(dir))==NULL){

printf("%s/n","打开目录失败");
return;
}
chdir(dir);
while((entry=readdir(dp))!=NULL){
stat(entry->d_name,&buf);
if(S_IFDIR&buf.st_mode){//如果是目录

if(strcmp(".",entry->d_name)==0||strcmp("..",entry->d_name)==0){//如果是当前为空目录

continue;//退出本次循环
}

delete(entry->d_name);//如果不是空目录,递归的调用d_name
 rmdir(entry->d_name);
}
else {
 unlink(entry->d_name);//如果是文件,则直接删除
}
}
closedir(dp);
chdir("..");
}

此程序首先创建了TestDir这个目录,并且创建了子目录subdir和子文件file,在subdir子目录中又创建了文件file1.

然后调用函数scan_dir显示了TestDir下面的所有目录和文件。

最后调用delete方法删除TestDir目录和目录下的所有子目录和文件。

 

几个重要的结构体:

stat结构体保存文件属性或状态信息

struct stat
{
dev_t st_dev; /* ID of device containing file */
ino_t st_ino; /* inode number */
mode_t st_mode; /* protection */
nlink_t st_nlink; /* number of hard links */
uid_t st_uid; /* user ID of owner */
gid_t st_gid; /* group ID of owner */
dev_t st_rdev; /* device ID (if special file) */
off_t st_size; /* total size, in bytes */
blksize_t st_blksize; /* blocksize for filesystem I/O */
blkcnt_t st_blocks; /* number of blocks allocated */
time_t st_atime; /* time of last access */
time_t st_mtime; /* time of last modification */
time_t st_ctime; /* time of last status change */
};

 

 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 */
char d_name [NAME_MAX+1]; /* file name (null-terminated) */
}

DIR结构体:

typedef struct {
   int dd_fd; /* file descriptor */
   int dd_loc; /* offset in block */
   int dd_size; /* amount of valid data */
    char *dd_buf; /* directory block */
   } DIR;

 

DIR称为目录流指针,dirent称为目录流实体.

 

操作文件的流程如下: 返回目录流指针->返回这个目录流指针指向的下一个目录实体->关闭目录流指针

 opendir(const char* f_path)->readdir(DIR *dp)->closedir(DIR *dp);

 

 

以上是简单文件操作的例子,至此,我们就可以模拟linux下的ls和rm命令。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值