linux--common func--目录操作相关

51 篇文章 6 订阅

创建目录和列出目录功能最常使用。

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描述了文件的类型,有多种取值,最重要的是848-常规文件(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"));//创建文件夹并创建文件
}
`struct sdio_func`是Linux内核中表示SDIO设备的结构体,它包含了SDIO设备的各种信息。在Linux内核中,每个SDIO设备都对应着一个`struct sdio_func`结构体,通过该结构体可以访问SDIO设备的寄存器、执行SDIO命令、发送和接收数据等。 `struct sdio_func`结构体定义如下: ``` struct sdio_func { u32 num; // SDIO设备的编号 struct mmc_card *card; // 对应的MMC卡 struct mmc_host *host; // 所在的MMC主机 unsigned int max_blksize; // 最大块大小 unsigned int cur_blksize; // 当前块大小 unsigned int enable_timeout_ms; // 使能超时时间 unsigned int io_abort; // 是否中断IO操作 void *class_dev; // 对应的设备结构体 struct sdio_func_tuple *tuples; // SDIO Tuple列表 unsigned int num_info; // Tuple的数量 unsigned int state; // SDIO设备状态 unsigned int irq_handler; // 中断处理函数 void *irq_data; // 中断处理函数的参数 unsigned int card_busy; // 卡忙标志 unsigned int ocr; // OCR寄存器的值 unsigned int cccr; // CCCR寄存器的值 unsigned int cisd; // CISD寄存器的值 unsigned int sdio_irqs; // SDIO中断标志 unsigned int num_funcs; // SDIO设备的函数数 struct sdio_func_tuple *common_cis; // 公共CIS struct sdio_func_tuple *cis; // CIS struct sdio_func_tuple *cccr_func; // CCCR函数 struct sdio_func_tuple *tuples_buf; // Tuple缓存 unsigned int max_busy_timeout; // 最大卡忙超时时间 unsigned int max_timeout; // 最大超时时间 unsigned int max_seg_size; // 最大段大小 unsigned int multi_block; // 是否支持多块传输 unsigned int no_preblock; // 不需要块预处理 unsigned int sdio_ver; // SDIO版本 unsigned int sd_ver; // SD版本 unsigned int sdio_funcs[8]; // SDIO设备的函数信息 struct device dev; // 对应的设备结构体 }; ``` `struct sdio_func`结构体中包含了SDIO设备的编号、对应的MMC卡、所在的MMC主机、最大块大小、当前块大小、使能超时时间、中断处理函数、设备结构体等信息。在使用`struct sdio_func`结构体时,可以根据SDIO设备的编号、MMC卡和MMC主机等信息来获取相应的`struct sdio_func`结构体,然后通过该结构体访问SDIO设备的寄存器、执行SDIO命令、发送和接收数据等。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值