Linux入门基础操作十三(linux下的文件操作相关函数)

Linux入门基础操作(ubuntu20.04)(十三)

stat函数:获取文件的属性信息

stat的使用
在这里插入图片描述
man 2 stat:查看对应man文档
在这里插入图片描述
stat函数与lstat函数的区别:
stat:可以穿透(追踪)函数 – 软链接
lstat:不可以穿透(追踪)函数

追踪示意图:
在这里插入图片描述

编辑stat(lstat)内部函数:

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

int main(int argc,char* argv[1])
{
if(argc < 2)
{
printf("./a.out filename\n");
exit(1);
}

struct stat st;
//struct stat* st;
int ret = stat(argv[1],&st);
//int ret = lstat(argv[1],&st);
if(ret == -1)
{
perror("stat");
exit(1);
}

//获取文件大小
int size = (int)st.st_size;
printf("file size = %d\n",size);
}

创建123.txt文件的软链接123.soft
在这里插入图片描述
stat函数下的终端命令执行:
在这里插入图片描述
lstat函数下的终端命令执行:
在这里插入图片描述
自制ls命令函数(ls-l.c):

#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <stdlib.h>
#include <time.h>
#include <pwd.h>
#include <grp.h>

int main(int argc,char* argv[])
{
if(argc < 2)
{
printf("./a.out filename\n");
exit(1);
}

struct stat st;
int ret = stat(argv[1],&st);
if(ret == -1)
{
perror("stat");
exit(1);
}

//存储文件类型和访问权限
char perms[11] = {0};
//判断文件类型
switch(st.st_mode & S_IFMT)
{
case S_IFLNK:
	perms[0] = '1';
	break;
case S_IFDIR:
	perms[0] = 'd';
	break;
case S_IFREG:
	perms[0] = '-';
	break;
case S_IFBLK:
	perms[0] = 'b';
	break;
case S_IFCHR:
	perms[0] = 'c';
	break;
case S_IFSOCK:
	perms[0] = 's';
	break;
case S_IFIFO:
	perms[0] = 'p';
	break;
default:
	perms[0] = '?';
	break;

}
//判断文件的访问权限
//文件所有者
perms[1] = (st.st_mode & S_IRUSR) ? 'r' : '-';
perms[2] = (st.st_mode & S_IWUSR) ? 'w' : '-';
perms[3] = (st.st_mode & S_IXUSR) ? 'x' : '-';
//文件所属组
perms[4] = (st.st_mode & S_IRGRP) ? 'r' : '-';
perms[5] = (st.st_mode & S_IWGRP) ? 'w' : '-';
perms[6] = (st.st_mode & S_IXGRP) ? 'x' : '-';
//其他人
perms[7] = (st.st_mode & S_IROTH) ? 'r' : '-';
perms[8] = (st.st_mode & S_IWOTH) ? 'w' : '-';
perms[9] = (st.st_mode & S_IXOTH) ? 'x' : '-';

//硬连接计数
int linkNum = st.st_nlink;
//文件所有者
char* fileUser = getpwuid(st.st_uid) ->pw_name;
//文件所属组
char* fileGrp = getgrgid(st.st_gid) ->gr_name;
//文件大小
int filesize = (int)st.st_size;
//修改时间
char* time = ctime(&st.st_mtime);
char mtime[512] = {0};
strncpy(mtime,time,strlen(time)-1);

char buf[1024];
sprintf(buf,"%s %d %s %s %d %s %s",perms,linkNum,fileUser,fileGrp,filesize,mtime,argv[1]);

printf("%s\n",buf);

return 0;
}

终端执行:
在这里插入图片描述

access函数:判断文件是否拥有某些权限

R_OK:是否有读权限
W_OK:是否有写权限
X_OK:是否有执行权限
F_OK:测试一个文件是否存在

#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>

int main(int argc,char*argv[])
{
if (argc < 2)
{
printf("a.out filename\n");
exit(1);
}

int ret = access(argv[1],W_OK);
if (ret == -1)
{
perror("access");
exit(1);
}
printf("you can write this file.\n");
return 0;
}

chomd函数:更改文件权限

#include <stdio.h>
#include<stdlib.h>
#include<sys/stat.h>

int main(int argc,char*argv[])
{
if(argc < 2)
{
printf("a.out filename\n");
exit(1);
}

int ret = chmod(argv[1],0777);
if(ret == -1)
{
perror("chmod");
exit(1);
}
return 0;
}


chown函数:修改文件所有者

#include<stdio.h>
#include<stdlib.h>

int main(int argc,char* argv[])
{
if (argc < 2)
{
printf("a.out filename\n");
exit(1);
}

// user->ftp  group->ftp
int ret = chown(argv[1],116,125);
if(ret == -1)
{
perror("chown");
exit(1);
}
return 0;
}

116和125代表的是用户ID和组ID
vi /etc/passwd:查看用户ID和组ID

truncate函数

在这里插入图片描述
文件长度为100;
第二个参数指定为20:保留前20
第二个参数指定为300:文件拓展至300

链接

link函数:创建一个硬链接
symlink函数:创建一个软链接
readlink函数:读软链接对应的文件名,不是读内容
unlink函数:删除一个文件的目录项并减少他的链接数,若成功则返回0,失败返回-1,错误原因存于errno.若果想通过调用这个函数来成功删除文件,你就必须拥有这个文件的所属目录的写和执行权限.

unlink函数的使用:
1.如果是符号链接,删除符号链接
2.如果是硬链接,硬链接数减一,当减为0时,释放数据块和inode
3.如果文件硬链接数为0,但有进程已打开该文件,并持有文件描述符,则等该进程关闭文件时,kernel才真正去删除文件(利用该特性可以创建临时文件)

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

int main()
{
int fd = open("tempfile",O_CREAT | O_RDWR,0664);
if(fd == -1)
{
perror("open");
exit(1);
}

//删除临时文件
int ret = unlink("tempfile");

//写入文件
write(fd,"hello\n",6);

//重置文件指针
lseek(fd,0,SEEK_SET);

//读取文件
char buf[24] = {0};
int len = read(fd,buf,sizeof(buf));

//将读出的内容,写到屏幕上
write(1,buf,len);

//关闭文件
close(fd);
return 0;

}

rename:重命名

**头文件:stdio.h
函数原型:int rename(const char oldpath,const char newpath);

关于目录的操作:

chair:修改当前进程路径

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

int main(int argc,char* argv[])
{
if (argc < 2)
{
printf("a.out dir\n");
exit(1);
}

int ret = chdir(argv[1]);
if (ret == -1)
{
perror("chdir");
exit(1);
}

int fd = open("chdir.txt",O_CREAT | O_RDWR,0777);
if (fd == -1)
{
perror("open");
exit(1);
}
close(fd);

char buf[128];
getcwd(buf,sizeof(buf));
printf("current dir:%s\n",buf);

return 0;
}

getcwd:获取当前进程工作目录
mkdir:创建目录(创建的目录需要有执行权限,否则无法进入目录)
rmdir:删除一个空目录
opendir:打开一个目录(返回值是DIR结构指针,该结构是一个内部结构,保存所打开的目录,作用类似于FILE结构,函数出错返回NULL)
readdir:读目录
closedir:关闭目录

#include<stdio.h>
#include<stdlib.h>
#include<sys/types.h>
#include<dirent.h>

int getFileNum(char* root)
{
// open dir
DIR* dir = NULL;
dir = opendir(root);
if(dir == NULL)
{
perror("opendir");
exit(1);
}

//遍历当前打开的目录
struct dirent* ptr = NULL;
char path[1024] = {0};
int total = 0;
while( (ptr = readdir(dir)) != NULL)
{
//过滤.和..
if (strcmp(ptr->d_name,".") == 0 || strcmp(ptr->d_name,"..") == 0)
{
continue;
}
//如果是目录
if (ptr->d_type == DT_DIR)
{
// 递归 读目录
sprintf(path,"%s/%s",root,ptr->d_name);
total += getFileNum(path);
}

// 如果是普通文件
if(ptr->d_type == DT_REG)
{
total++;
}
}

closedir(dir);
return total;
}

int main(int argc,char* argv[])
{
if (argc <2)
{
printf("./a.out dir\n");
exit(1);
}

int total = getFileNum(argv[1]);
printf("%s has file numbers %d\n",argv[1],total);

	return 0;
}

dup dup2:复制文件描述符

dup:

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

int main()
{
int fd = open("a.txt",O_RDWR);
if(fd == -1)
{
perror("open");
exit(1);
}

printf("file open fd = %d\n",fd);

//找到进程文件描述符表中 ==第一个== 可用的文件名描述符
//将参数指定的文件复制到该描述符后,返回这个描述符
int ret = dup(fd);
if(ret == -1)
{
perror("dup");
exit(1);
}
printf("dup fd = %d\n",ret);
char* buf = "你是猴子派来的救兵吗????\n";
char* buf1 = "你大爷的,我是你爸爸!!!\n";
write(fd,buf,strlen(buf));
write(ret,buf1,strlen(buf1));

close(fd);
return 0;
}

dup2:

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

int main()
{
int fd = open("english.txt",O_RDWR);
if(fd == -1)
{
perror("open");
exit(1);
}
int fd1 = open("a.txt",O_RDWR);
if(fd == -1)
{
perror("open");
exit(1);
}
printf("fd = %d\n",fd);
printf("fd1 = %d\n",fd1);

int ret = dup2(fd1,fd);
if(ret == -1)
{
perror("dup2");
exit(1);
}
printf("CURRENT FD = %d\n",ret);
char* buf ="主要看气质^_^!!!!!!!!!!\n";
write(fd,buf,strlen(buf));
write(fd1,"hello,world!",13);

close(fd);
close(fd1);
return 0;
}

fcntl:改变已经打开文件的属性

#include<stdio.h>
#include<stdlib.h>
#include<fcntl.h>
#include<unistd.h>
#include<string.h>

int main(void)
{
int fd;
int flag;

//测试字符串
char *p = "sdhfjhjkfkjsdfkjd\n";
char *q = "lksdjfjkldsjslkdjf.......";

//只写的方式打开文件
fd = open("test.txt",O_WRONLY);
if (fd == -1)
{
perror("open");
exit(1);
}

//输入新的内容,该部分会覆盖原来旧 的内容
if(write(fd,p,strlen(p)) == -1)
{
perror("write");
exit(1);
}

//使用 F_GETFL 命令得到文件状态标志
flag = fcntl(fd,F_GETFL,0);
if (flag == -1)
{
perror("fcntl");
exit(1);
}

//将文件状态标志添加“追加写”选项
flag |= O_APPEND;
//将文件状态修改为追加写
if(fcntl(fd,F_SETFL,flag) == -1)
{
perror("fcntl -- append write");
exit(1);
}

//再次输入新内容,该内容会追加到旧内容的后面
if(write(fd,q,strlen(q)) == -1)
{
perror("write again");
exit(1);
}
//关闭文件
close(fd);

return 0;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值