创建目录和列出目录功能最常使用。
1. 获取当前工作目录
1.1 Linux command
在shell中我们可以直接输入命令pwd
来显示当前的工作目录
1.2 C
在C程序中调用getcwd
函数可以获取当前的工作目录。
函数声明:
char *getcwd(char * buf,size_t size);
当前工作目录存入buf中
#include <unistd.h>
返回值:
如果目录名超出了参数size长度,函数返回NULL,如果成功,返回buf。
例如:
char strpwd[301];
memset(strpwd,0,sizeof(strpwd));
getcwd(strpwd,300);
printf("当前目录是:%s\n",strpwd);
```
示例:
```c
void main()
{
char * strpwd=malloc(301);
memset(strpwd,0,sizeof(strpwd));
printf("strpwd=%p\n",strpwd);
printf("res=%p\n",getcwd(strpwd,300));
printf("当前目录是:%s\n",strpwd);
free(strpwd);
}
2. 切换工作目录
2.1 Linux
在shell中我们可以直接输入命令cd
来显示当前的工作目录
2.2 C
C中用chdir
函数切换目录
函数声明:
int chdir(const char *path);
就像我们在shell中使用cd命令切换目录一样,在C程序中使用chdir函数来改变工作目录。
#include <unistd.h>
返回值:0-切换成功;非0-失败。
```
示例:
```c
char * strpwd1=malloc(301);
memset(strpwd1,0,sizeof(strpwd1));
chdir("aaa");
getcwd(strpwd1,300);
printf("当前目录是:%s\n",strpwd1);
3. 目录的创建和删除
3.1 Linux
我们可以在shell中可以通过 mkdir/rmdir 命令
来创建/删除目录
3.2 C
C程序中用 mkdir/rmdir 函数
来创建/删除目录。
创建目录函数的声明:
int mkdir(const char *pathname, mode_t mode);
#include <sys/stat.h>
返回值:创建一个目录,若成功则返回0,否则返回-1 。
mode的含义将按open系统调用的O_CREAT选项中的有关定义设置,
当然,它还要服从umask的设置况,是不是看不明白?
那先固定填0755,注意:0不要省略哦,它表示八进制。
例如:
mkdir("/tmp/aaa",0755); // 创建/tmp/aaa目录
返回值:
若目录创建成功,则返回0;否则返回-1,并将错误记录到全局变量errno中。
删除目录函数的声明:
int rmdir(const char *pathname);
返回值:若成功则返回0,否则返回-1
mkdir示例:
#include <sys/stat.h>//ubuntu
void main()
{
mkdir("ddd",0755);//在程序所在文件夹下创建一个名为ddd的文件夹
mkdir("aaa/ddd",0755);//使用这种多文件夹方式创建文件夹时要注意:最后一个文件夹名前面的文件夹都存在,否则就一直返回-1
//已存在的文件再次创建也会报错
}
```
**rmdir示例:**
```c
#include <sys/stat.h>
void main()
{
rmdir("bbb");//如果文件夹中有文件或文件夹也会一直报错,里面是空的才会删除成功。
rmdir("aaa/bbb");//一定要保证aaa存在,否则报错
}
4. 获取目录中的文件列表
4.1 Linux
我们可以在shell中可以通过 ls
命令来获取目录中的文件列表
4.2 C
4.2.1 相关函数
#include <dirent.h>//包含头文件
相关的库函数(配合使用):
打开目录的函数opendir的声明:
DIR *opendir(const char *pathname);
读取目录的函数readdir的声明:
struct dirent *readdir(DIR *dirp);
关闭目录的函数closedir的声明:
int closedir(DIR *dirp);
目录指针DIR:
DIR *目录指针名;
readdir读取目录函数返回值为struct dirent结构体:
每调用一次readdir函数会返回一个struct dirent的地址,存放了本次读取到的内容,它的原理与fgets函数读取文件相同。
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文件名,最长255字符
};
我们只需要关注结构体的d_type和d_name成员,其它的不必关心。
d_name文件名或目录名。
d_type描述了文件的类型,有多种取值,最重要的是8和4,8-常规文件(A regular file);4-目录(A directory),其它的暂时不关心。
4.2.2 获取目录中的文件列表示例:
#include <stdio.h>
#include <dirent.h>
int main(int argc,char *argv[])
{
if (argc != 2) { printf("请指定目录名。\n"); return -1; }
DIR *dir; // 定义目录指针
// 打开目录
if ( (dir=opendir(argv[1])) == 0 ) return -1;
// 用于存放从目录中读取到的文件和目录信息
struct dirent *stdinfo;
while (1)
{
// 读取一条记录并显示到屏幕
if ((stdinfo=readdir(dir)) == 0) break;
printf("name=%s,type=%d\n",stdinfo->d_name,stdinfo->d_type);
}
closedir(dir); // 关闭目录指针
}
4.2.3 获取目录中的文件列表实例
-
文件存放在某目录中,该目录下还会有多级子目录,程序员想要的是列出该目录及其子目录下全部的文件名。
例如存在/home/wucz/tmp目录,其子目录结构和文件如下:
-
实现:
#include <stdio.h> #include <dirent.h> // 列出目录及子目录下的文件 int ReadDir(const char *strpathname); int main(int argc,char *argv[]) { if (argc != 2) { printf("请指定目录名。\n"); return -1; } // 列出目录及子目录下的文件 ReadDir(argv[1]); } // 列出目录及子目录下的文件 int ReadDir(const char *strpathname) { DIR *dir; // 定义目录指针 char strchdpath[256]; // 子目录的全路径 if ( (dir=opendir(strpathname)) == 0 ) return -1; // 打开目录 struct dirent *stdinfo; // 用于存放从目录读取到的文件和目录信息 while (1) { if ((stdinfo=readdir(dir)) == 0) break; // 读取一记录 if (strncmp(stdinfo->d_name,".",1)==0) continue; // 以.开始的文件不读 if (stdinfo->d_type==8) // 如果是文件,显示出来 printf("name=%s/%s\n",strpathname,stdinfo->d_name); if (stdinfo->d_type==4) // 如果是目录,再调用一次ReadDir { sprintf(strchdpath,"%s/%s",strpathname,stdinfo->d_name); ReadDir(strchdpath); } } closedir(dir); // 关闭目录指针 }
运行效果:
5. 获取当前用户对文件或目录的存取权限
5.1 Linux
利用ls -l
命令
ls -l xxx.xxx (xxx.xxx是文件名)
执行结果标识符释义:
r 表示文件可以被读(read)
w 表示文件可以被写(write)
x 表示文件可以被执行(如果它是程序的话)
- 表示相应的权限还没有被授予
之后的root root 就是用户拥有者了
示例:
上面示例解释:
一共有十位数,其中:
最前面那个 - 代表的是类型
中间那三个 rw- 代表的是所有者(user)拥有的权限
然后那三个 r-- 代表的是组群(group)拥有的权限
最后那三个 r-- 代表的是其他人(other)拥有的权限
- 需要注意的是:
查看文件权限的目录问题: 如果有文件夹 /a/b/c 那么执行 ls -l /a/b 查看权限的文件并不是b,而是查看的c的权限。 ls -l /a 查看的是b文件的权限 ls -l /a/b 查看的是c文件的权限 ls -l /a/b/c 查看的是c文件的权限
5.2 C
5.2.1 获取文件或文件夹权限函数
access
函数用于判断当前操作系统用户对文件或目录的存取权限。
包含头文件:
#include <unistd.h>
函数声明:
int access(const char *pathname, int mode);
参数说明:
pathname文件名或目录名,可以是当前目录的文件或目录,也可以列出全路径。
mode 需要判断的存取权限。在头文件unistd.h中的预定义如下:
#define R_OK 4 // R_OK 只判断是否有读权限
#define W_OK 2 // W_OK 只判断是否有写权限
#define X_OK 1 // X_OK 判断是否有执行权限
#define F_OK 0 // F_OK 只判断是否存在
返回值:
当pathname满足mode的条件时候返回0,不满足返回-1。
在实际开发中,access函数主要用于判断文件或目录是否是存在。
access
示例代码:
#include <unistd.h>
#include <stdio.h>
void main()
{
if(access("aaa1",F_OK)==0)
printf("exist\n");
}
5.2.2 获取文件和目录的状态信息
就是创建时间之类的信息。
stat
库函数:
包含头文件:
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
函数声明:
int stat(const char *path, struct stat *buf);
参数说明:获取path指定文件或目录的信息,将信息保存到结构体buf中
返回值:执行成功返回0,失败返回-1。
stat
结构体:
struct stat结构体用于存放文件和目录的状态信息,如下:
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 最近一次被更改的时间, 此参数会在文件所有者、组、 权限被更改时更新
};
struct stat结构体的成员变量比较多;
对程序员来说,重点关注st_mode、st_size和st_mtime成员就可以了。
注意st_mtime是一个整数表达的时间,需要程序员自己写代码转换格式(使用localtime库函数)。
st_mode成员的取值很多,或者使用如下两个宏来判断:
S_ISREG(st_mode) // 是否为一般文件
S_ISDIR(st_mode) // 是否为目录
示例:
#include <time.h>
#include <sys/time.h>
#include <utime.h>
#include <stdio.h>
int timetostr(const time_t ti,char *strtime)
{//把整数的时间转换为字符串格式的时间
struct tm * now=localtime(&ti);
if(now!=0)
{
sprintf(strtime,"%d-%02u-%02u %02u:%02u:%02u", now->tm_year+1900,now->tm_mon,now->tm_mday,now->tm_hour,now->tm_min,now->tm_sec);
return 0;
}
return -1;
}
void main()
{
char statstr[20];
struct stat statTemp;
if(stat("aaa1",&statTemp)==0)
{
timetostr(statTemp.st_mtime,statstr);
printf("statTemp.st_mtime=%s st_size=%ld\n",statstr,statTemp.st_size);
}
}
6. 修改存取时间和更改时间
6.1 linux command
6.1.1 同时变更文件的修改时间和访问时间(Access&Modify)
pl@pl-virtual-machine:~/Desktop/LPGitHub/CPP/C_Basics$ touch -d "2018-04-18 08:00:00" aaa
pl@pl-virtual-machine:~/Desktop/LPGitHub/CPP/C_Basics$ stat aaa
File: aaa
Size: 4096 Blocks: 8 IO Block: 4096 directory
Device: 805h/2053d Inode: 1056464 Links: 3
Access: (0775/drwxrwxr-x) Uid: ( 1000/ pl) Gid: ( 1000/ pl)
Access: 2018-04-18 08:00:00.000000000 +0800
Modify: 2018-04-18 08:00:00.000000000 +0800
Change: 2021-10-22 15:25:50.968267483 +0800
Birth: -
6.1.2 只变更文件的修改时间(Modify)
pl@pl-virtual-machine:~/Desktop/LPGitHub/CPP/C_Basics$ touch -m -d "2018-05-20 08:00:00" aaa
pl@pl-virtual-machine:~/Desktop/LPGitHub/CPP/C_Basics$ stat aaa
File: aaa
Size: 4096 Blocks: 8 IO Block: 4096 directory
Device: 805h/2053d Inode: 1056464 Links: 3
Access: (0775/drwxrwxr-x) Uid: ( 1000/ pl) Gid: ( 1000/ pl)
Access: 2018-04-18 08:00:00.000000000 +0800
Modify: 2018-05-20 08:00:00.000000000 +0800
Change: 2021-10-22 15:26:59.712269446 +0800
Birth: -
6.1.3 只变更文件的访问时间(Access)
pl@pl-virtual-machine:~/Desktop/LPGitHub/CPP/C_Basics$ touch -a -d "2017-05-10 09:00:00" aaa
pl@pl-virtual-machine:~/Desktop/LPGitHub/CPP/C_Basics$ stat aaa
File: aaa
Size: 4096 Blocks: 8 IO Block: 4096 directory
Device: 805h/2053d Inode: 1056464 Links: 3
Access: (0775/drwxrwxr-x) Uid: ( 1000/ pl) Gid: ( 1000/ pl)
Access: 2017-05-10 09:00:00.000000000 +0800
Modify: 2018-05-20 08:00:00.000000000 +0800
Change: 2021-10-22 15:28:20.148271742 +0800
Birth: -
6.2 c func
utime
库函数,用于修改文件的存取时间和更改时间:
包含头文件:
#include <utime.h>
函数声明:
int utime(const char *filename, const struct utimbuf *times);
参数说明:
filename:要修改的文件名字符串
times:如果参数times为空指针(NULL), 则该文件的存取时间和更改时间全部会设为目前时间。
结构utimbuf 定义如下:
struct utimbuf
{
time_t actime;
time_t modtime;
};
返回值:执行成功则返回0,失败返回-1。
示例:
#include <utime.h>
#include <stdio.h>
#include <time.h>
void main()
{
struct utimbuf utimTemp;
utimTemp.actime=time(0);
utimTemp.modtime=time(0);
if(utime("aaa1",&utimTemp)==0)//文件夹名字aaa1
{
printf("modify aaa1 time success!");
}
}
7. 重命名文件或目录
7.1 Linux command
mv file1 file2
#把当前目录下的file1文件名改成file2,如果该目录下有file2,则覆盖以前的file2文件
7.2 c func
rename
函数用于重命名文件或目录.相当于Linux的mv命令
包含头文件:
#include <stdio.h>
函数声明:
int rename(const char *oldpath, const char *newpath);
参数说明:
//oldpath 文件或目录的原名。
//newpath 文件或目录的新的名称。
返回值:0-成功,-1-失败。
示例:
在这里插入代码片
9. 删除文件或目录
9.1 linux command
删除文件用:rm 文件名
删除空文件夹用:rmdir 文件夹名。
删除非空文件夹:rm -rf 非空文件夹名
-r 就是向下递归,不管有多少级目录,一并删除。
-f 就是直接强行删除,不作任何提示的意思。
9.2 c func
remove
函数用于删除文件或目录,相当于操作系统的rm命令。
包含头文件:
#include <stdio.h>
函数声明:
int remove(const char *pathname);
参数说明:
pathname 待删除的文件或目录名。
返回值:0-成功,-1-失败。
示例:
#include <stdio.h>
void main()
{
if(remove("aaa11")==0)//aaa1文件夹中不为空就失败
{
printf("rm aaa11 success!\n");
}
else
printf("rm aaa11 failed\n");
if(remove("bbb")==0)//bbb是空文件夹名 成功
printf("rm bbb success!\n");
}
other. 利用所学知识编写函数
1. mkdir创建多级目录实例
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
int Customize_mkdir(const char *path )
{
if(strstr(path,"/")==NULL)
{
if(access(path,F_OK)!=0)//F_OK是否存在该文件名
{
if(mkdir(path,0755)!=0)//第二个参数加0时是表示八进制
{
printf("create %s failed!\n",path);
return -1;
}
}
else
{
printf("%s:This ictionary exist\n",path);
return -1;
}
}
else
{
//example:"temp/aaa/bbb/ccc/testfile.c"
// 123456789 13 17 27
char * index=0;
char * strtemp=malloc(301);
int n=0;//累加/前面的字符,包含当前/
memset(strtemp,0,sizeof(301));
while(1)
{
index=strstr((path+n),"/");//动态找到第几个/
if(index==0)
{
char *dot=strstr(path+n,".");//find . position
if(dot!=0)//最后/后面是文件名
{
FILE * filetemp=fopen(path+n,"w");//如果文件存在,则清除原文件内容;如果文件不存在,则新建文件。
if(filetemp==NULL)
return -1;
fclose(filetemp);
}
else//最后/后面是文件夹名
{
strncpy(strtemp,path+n,strlen(path)-n);
mkdir(strtemp,0755);
chdir(strtemp);
}
break;
}
if(n==0)
strncpy(strtemp,path+n,index-(path+n));
else
strncpy(strtemp,path+n,index-(path+n+1));
n=(index-path)+1;
mkdir(strtemp,0755);
chdir(strtemp);//cd new path
//printf("%s 创建成功!\n",strtemp);
memset(strtemp,0,301);
}
free(strtemp);
}
return 0;//成功返回0
}
void main()
{
printf("res=%d\n",Customize_mkdir("temp1/aaa"));//创建两个文件夹
printf("res=%d\n",Customize_mkdir("temp1/a.c"));//创建文件夹并创建文件
}