Linux&C语言 目录 *** 作

Linux&C语言 目录 *** 作,第1张

Linux&C语言 目录 *** 作

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

一、获取当前工作目录

1. Linux
在shell中我们可以直接输入命令pwd 来显示当前的工作目录

2. C
在C程序中调用getcwd函数可以获取当前的工作目录。

函数声明:
char *getcwd(char * buf,size_t size);
当前工作目录存入buf中
#include 
返回值:
如果目录名超出了参数size长度,函数返回NULL,如果成功,返回buf。

例如:
char strpwd[301];
memset(strpwd,0,sizeof(strpwd));
getcwd(strpwd,300);
printf("当前目录是:%sn",strpwd);

示例:

void main()
{                               
    char * strpwd=malloc(301);
    memset(strpwd,0,sizeof(strpwd));
    printf("strpwd=%pn",strpwd);
    printf("res=%pn",getcwd(strpwd,300));
    printf("当前目录是:%sn",strpwd);
    free(strpwd);
}
二、切换工作目录

1. Linux
在shell中我们可以直接输入命令cd 来显示当前的工作目录
2. C
C中用chdir函数切换目录

函数声明:
int chdir(const char *path);
就像我们在shell中使用cd命令切换目录一样,在C程序中使用chdir函数来改变工作目录。 
#include 
返回值:0-切换成功;非0-失败。

示例:

char * strpwd1=malloc(301);
memset(strpwd1,0,sizeof(strpwd1));
chdir("aaa");
getcwd(strpwd1,300);
printf("当前目录是:%sn",strpwd1);
三、目录的创建和删除

1. Linux
我们可以在shell中可以通过mkdir/rmdir命令来创建/删除目录
2. C
C程序中用mkdir/rmdir函数来创建/删除目录。

创建目录函数的声明:
int mkdir(const char *pathname, mode_t mode);
#include 
返回值:创建一个目录,若成功则返回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 //ubuntu
void main()
{
	mkdir("ddd",0755);//在程序所在文件夹下创建一个名为ddd的文件夹
	mkdir("aaa/ddd",0755);//使用这种多文件夹方式创建文件夹时要注意:最后一个文件夹名前面的文件夹都存在,否则就一直返回-1
//已存在的文件再次创建也会报错
}

rmdir示例:

#include 
void main()
{
	rmdir("bbb");//如果文件夹中有文件或文件夹也会一直报错,里面是空的才会删除成功。
	rmdir("aaa/bbb");//一定要保证aaa存在,否则报错
	
}
四、获取目录中的文件列表

1. Linux
我们可以在shell中可以通过ls命令来获取目录中的文件列表
2. C

#include //包含头文件
相关的库函数(配合使用):

打开目录的函数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),其它的暂时不关心。

获取目录中的文件列表示例:

#include 
#include 
 
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=%dn",stdinfo->d_name,stdinfo->d_type);
  }
 
  closedir(dir);   // 关闭目录指针
}

获取目录中的文件列表实例:
文件存放在某目录中,该目录下还会有多级子目录,程序员想要的是列出该目录及其子目录下全部的文件名。

例如存在/home/wucz/tmp目录,其子目录结构和文件如下:

实现:

#include 
#include 
 
// 列出目录及子目录下的文件
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/%sn",strpathname,stdinfo->d_name);
 
    if (stdinfo->d_type==4)   // 如果是目录,再调用一次ReadDir
    {
      sprintf(strchdpath,"%s/%s",strpathname,stdinfo->d_name);
      ReadDir(strchdpath);
    }
  }
 
  closedir(dir);   // 关闭目录指针
}

运行效果:

五、获取当前用户对文件或目录的存取权限

1. Linux
利用ls命令

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文件的权限

2. C

- 获取权限

access函数用于判断当前 *** 作系统用户对文件或目录的存取权限。

包含头文件:
#include 

函数声明:
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 
#include 

void main()
{
	if(access("aaa1",F_OK)==0)
        printf("existn");
}

- 获取文件和目录的状态信息
就是创建时间之类的信息。
stat库函数:

包含头文件:
#include 
#include 
#include 

函数声明:
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 
#include 
#include 
#include 

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=%ldn",statstr,statTemp.st_size);
    }
}
六、修改存取时间和更改时间
  1. Linux
    参考链接
    ①同时变更文件的修改时间和访问时间(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: -

②只变更文件的修改时间(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: -

③只变更文件的访问时间(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: -
  1. C
    utime库函数,用于修改文件的存取时间和更改时间:
包含头文件:
#include 

函数声明:
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 
#include 
#include 

void main()
{
	struct utimbuf utimTemp;
    utimTemp.actime=time(0);
    utimTemp.modtime=time(0);
    if(utime("aaa1",&utimTemp)==0)//文件夹名字aaa1
    {
        printf("modify aaa1 time success!");
    }   
}
七、重命名文件或目录
  1. Linux
mv file1 file2
#把当前目录下的file1文件名改成file2,如果该目录下有file2,则覆盖以前的file2文件
  1. C
    rename函数用于重命名文件或目录.相当于Linux的mv命令
包含头文件:
#include 

函数声明:
int rename(const char *oldpath, const char *newpath);

参数说明:
//oldpath 文件或目录的原名。
//newpath 文件或目录的新的名称。

返回值:0-成功,-1-失败。

示例:

在这里插入代码片
八、删除文件或目录
  1. Linux
删除文件用:rm 文件名
删除空文件夹用:rmdir 文件夹名。
删除非空文件夹:rm -rf 非空文件夹名

-r 就是向下递归,不管有多少级目录,一并删除。
-f 就是直接强行删除,不作任何提示的意思。
  1. C
    remove函数用于删除文件或目录,相当于 *** 作系统的rm命令。
包含头文件:
#include 

函数声明:
int remove(const char *pathname);

参数说明:
pathname 待删除的文件或目录名。

返回值:0-成功,-1-失败。

示例:

#include 

void main()
{
	if(remove("aaa11")==0)//aaa1文件夹中不为空就失败
    {
        printf("rm aaa11 success!n");
    }
    else
        printf("rm aaa11 failedn");

    if(remove("bbb")==0)//bbb是空文件夹名 成功
        printf("rm bbb success!n");
}
利用所学知识编写函数

1. mkdir创建多级目录

#include 
#include 
#include 
#include 

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 existn",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=%dn",Customize_mkdir("temp1/aaa"));//创建两个文件夹
	printf("res=%dn",Customize_mkdir("temp1/a.c"));//创建文件夹并创建文件
}

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zaji/4751795.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-11-08
下一篇 2022-11-08

发表评论

登录后才能评论

评论列表(0条)

保存