7 Linux系统编程-目录操作
7.1 文件目录比较和rwx差异
获取进程当前工作目录:卷3 标准库函数
char *getcwd(char *buf, size_t size) 成功将buf保存当前进程工作目录的位置,失败将返回NULL
改变当前进程工作目录:
int chdir(const char *path); 成功:0 失败:-1设置errno的值
文件/目录权限
文件的内容是写到文件的内容,目录的内容是目录项
r | w | x | |
---|---|---|---|
文件 | 文件内容可以被查看 cat more less | 内容可以被修改 | 可以运行产生一个进程./文件名 |
目录 | 目录可以被浏览 ls tree | 创建 删除 修改文件 mv touch mkdir | 可以被打开,进入 cd |
7.2 目录操作函数 5.12
(库函数) man 3 functionname
函数:DIR opendir(const char name)
描述:
The opendir() function opens a directory stream corresponding to the directory name, and returns a pointer to the directory stream.The stream is positioned at the first entry in the directory.
The fdopendir() function is like opendir(), but returns a directory stream for the directory referred to by the open file descriptor fd.
After a successful call to fdopendir(), fd is used internally by the implementation, and should not otherwise be used by the application.
头文件:#include<sys/types.h> #include <dirent.h>
参数:const char* name 文件夹名字
返回值:DIR* 返回一个目录流的指针,和FILE*类似
如果发生错误,将会返回一个空指针;并且设置erron;
函数:int closedir(DIR dirp)*
头文件:#include <sys/types.h> #include<dirent.h>
描述:关闭目录流,同样也会关闭目录文件的描述符
参数:DIR* dirp 一个文件流指针
返回值:int值,0代表成功,-1代表失败,并且设置erron
函数:struct dirent readdir(DIR dirp)
头文件:#include<dirent.h>
描述:
The readdir() function returns a pointer to a dirent structure representing the next directory entry in the directory stream pointed to by dirp.It returns NULL on reaching the end of the directory stream or if an error occurred. In the glibc implementation, the dirent structure is defined as follows:
struct dirent {
ino_t d_ino; /* Inode number */
off_t d_off; /* Not an offset; see below */
unsigned short d_reclen;/* Length of this record */
unsigned char d_type; /* Type of file; not supported by all filesystem types */
char d_name[256]; /* Null-terminated filename */
};
返回值:成功,返回一个结构体,结构体由目录的各种信息,如果读到文件结尾或者失败,都返回NULL,区别两者的方法是读到结尾,不会修改errno,而读取失败,会修改errno的值。
//一段实现ls功能的代码
#include <stdio.h>
#include <unistd.h>
#include <dirent.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char** argv)
{
DIR* dir1=opendir(argv[1]);
if(dir1==NULL){
perror("open directory failed!\n");
exit(1);
}
struct dirent* dir_info;
while((dir_info=readdir(dir1))!=NULL){
//消除显示中的"."".."选项
if((!strcmp(dir_info->d_name,"."))||(!strcmp(dir_info->d_name,".."))){
continue;
}
printf("%s\t",dir_info->d_name);
}
printf("\n");
closedir(dir1);
return 0;
}
7.3 递归遍历目录实现 5.13
linux可以用 ls -R filename实现
#include <stdio.h>
#include <unistd.h>
//使用文件操作的宏定义
#include <fcntl.h>
//使用exit函数
#include <stdlib.h>
//使用stat函数
#include <sys/stat.h>
//使用目录相关函数
#include <dirent.h>
#include <string.h>
void isFile(char *args);
void lsr(char *args, void (*fnp)(char *))
{
char path[256];
DIR *dir_fd;
struct dirent *dir_info;
dir_fd = opendir(args);
{
if (dir_fd == NULL)
{
perror("open dir error!\n");
return;
}
}
while ((dir_info = readdir(dir_fd)) != NULL)
{
if (!((strcmp(dir_info->d_name, ".") && strcmp(dir_info->d_name, ".."))))
continue;
else
{
//字符串拼接,也可以考虑使用strcat
sprintf(path, "%s/%s", args, dir_info->d_name);
(*fnp)(path);
}
}
closedir(dir_fd);
}
//回调函数
void isFile(char *args)
{
//定义传出参数
struct stat statbuf;
int ret = stat(args, &statbuf);
if (ret == -1)
{
perror("open argv[1] failed!");
exit(1);
}
//判断文件类型,文件类型是文件夹,递归调用lsr
if ((statbuf.st_mode & __S_IFMT) == __S_IFDIR)
{
lsr(args, isFile);
}
//如果是普通文件,直接打印文件信息
if ((statbuf.st_mode & __S_IFMT) == __S_IFREG)
{
printf("%8ld\t%s\n", statbuf.st_size, args);
}
}
int main(int argc, char *argv[])
{
//如果参数个数等于1,也就是没有变量输入,使用“."代替,即查看当前目录
if (argc ==1)
{
isFile(".");
}
else{
isFile(argv[1]);
}
return 0;
}
7.4 重定向 dup和dup2 5.14
重定向:将写入标准输出的(STD_OUT)的内容写入一个文件
函数:int dup(int oldfd); int dup2(int oldfd, int newfd); int dup3(int oldfd, int newfd, int flags)
//dup2 dupto
dup主要实现文件描述符复制 dup2实现文件描述符重定向
描述:
The dup() system call creates a copy of the file descriptor oldfd, using the lowest-numbered unused file descriptor for the new descriptor.
After a successful return, the old and new file descriptors may be used interchangeably. They refer to the same open file description (see open(2)) and thus share file offset and file status flags; for example, if the file offset is modified by using lseek(2) on one of the file descriptors, the offset is also changed for the other.
The two file descriptors do not share file descriptor flags (the closeon-exec flag).The close-on-exec flag (FD_CLOEXEC; see fcntl(2)) for the duplicate descriptor is off.
头文件:#define _GPU_SOURCE #include <fcntl.h>
#include <unistd.h>
参数:int dup (int oldfd) oldfd 旧的文件描述符
int dup(int oldfd, int newfd) oldfd 旧的文件描述符
返回值:如果成功,这些系统调用都返回新的文件描述符,失败返回-1,设置erron;
shell中的重定义:
# 使用>重定向到out文件
cat myls.c > out
# 使用>>追加到out文件
cat myls.c >>out
DEMO1:
#include <unistd.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char* argv[])
{
if(argc!=2){
printf("wrong args!\n");
}
int oldfd=open(argv[1],O_RDONLY);
if(oldfd==-1){
perror("open file failed!");
exit(1);
}
int newfd=dup(oldfd);
printf("oldfd=%d\n",oldfd);
printf("newfd=%d\n",newfd);
close(oldfd);
close(newfd);
return 0;
}
daniel@daniel-Vostro-5471:~/文档/OS/test/IO_test$ ./dup link.c
oldfd=3
#新的文件描述符是4
newfd=4
DEMO2:
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdlib.h>
int main(int argc, char** argv)
{
if(argc!=2){
printf("args error!\n");
}
int fd1=open(argv[1],O_RDWR|O_CREAT,0664);
if(fd1==-1){
perror("open file failed!\n");
exit(1);
}
//将标准输出重定向到fd1
dup2(fd1,STDOUT_FILENO);
//下面的打印不会打印到屏幕,而是输出到argv[1]的文件中
printf("hello world!\n");
close(fd1);
return 0;
}
7.5 fcntl()实现dup功能 5.14
使用fcntl函数实现dup功能,fcntl函数的第二个参数是可调的,选择F_DUPFD 可以拷贝文件描述符
#include <unistd.h>
#include <fcntl.h>
int fcntl(int fd, int cmd, ... /* arg */ );
F_DUPFD (int)
Duplicate the file descriptor fd using the lowest-numbered
available file descriptor greater than or equal to arg. This is
different from dup2(2), which uses exactly the file descriptor
specified.
On success, the new file descriptor is returned.
See dup(2) for further details.
#include <unistd.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char* argv[])
{
if(argc!=2){
printf("wrong args!\n");
}
int oldfd=open(argv[1],O_RDWR|O_APPEND);
if(oldfd==-1){
perror("open file failed!");
exit(1);
}
//参数3可以指定文件描述符设置的起始位置
//函数会从这个起始位置向上寻找最小的文件描述符作为返回参数
int newfd=fcntl(oldfd,F_DUPFD,5);
printf("oldfd=%d\n",oldfd);
printf("newfd=%d\n",newfd);
write(newfd,"//12345678\n",11);
close(oldfd);
close(newfd);
return 0;
}