Linux的文件属性
一.文件类型有哪些,怎么看,怎么用
1.文件类型
普通文件(- regular file),包括文本文件和二进制文件
目录文件(d directory),本身不适合用普通的方式来读写,linux中是使用特殊的一些API来专门读写文件夹的
字符设备文件(c character),设备文件对应的是硬件设备,也就是说这个文件虽然在文件系统中存在,但是并不是真正存在于硬盘上的一个文件,而是文件系统虚拟制造出来的(叫虚拟文件系统,如/dev /sys /proc等)
管道文件(p pipe)
套接字文件(s socket)
符号链接文件(l link)
2.怎么看,怎么用
命令行中:stat 文件名
C程序中:
int stat(const char *pathname, struct stat *statbuf); int fstat(int fd, struct stat *statbuf); int lstat(const char *pathname, struct stat *statbuf);
struct stat {
dev_t st_dev; /* ID of device containing file */
ino_t st_ino; /* Inode number */
mode_t st_mode; /* File type and mode */
nlink_t st_nlink; /* Number of hard links */
uid_t st_uid; /* User ID of owner */
gid_t st_gid; /* Group ID of owner */
dev_t st_rdev; /* Device ID (if special file) */
off_t st_size; /* Total size, in bytes */
blksize_t st_blksize; /* Block size for filesystem I/O */
blkcnt_t st_blocks; /* Number of 512B blocks allocated */
/* Since Linux 2.6, the kernel supports nanosecond
precision for the following timestamp fields.
For the details before Linux 2.6, see NOTES. */
struct timespec st_atim; /* Time of last access */
struct timespec st_mtim; /* Time of last modification */
struct timespec st_ctim; /* Time of last status change */
#define st_atime st_atim.tv_sec /* Backward compatibility */
#define st_mtime st_mtim.tv_sec
#define st_ctime st_ctim.tv_sec
};
linux中文件类型宏定义(man 7 inode中查看)
S_IFMT 0170000 bit mask for the file type bit field S_IFSOCK 0140000 socket S_IFLNK 0120000 symbolic link S_IFREG 0100000 regular file S_IFBLK 0060000 block device S_IFDIR 0040000 directory S_IFCHR 0020000 character device S_IFIFO 0010000 FIFO Thus, to test for a regular file (for example), one could write: stat(pathname, &sb); if ((sb.st_mode & S_IFMT) == S_IFREG) { /* Handle regular file */ }
或者用下面的判断的方法
S_ISREG(m) is it a regular file? S_ISDIR(m) directory? S_ISCHR(m) character device? S_ISBLK(m) block device? S_ISFIFO(m) FIFO (named pipe)? S_ISLNK(m) symbolic link? (Not in POSIX.1-1996.) S_ISSOCK(m) socket? (Not in POSIX.1-1996.) The preceding code snippet could thus be rewritten as: stat(pathname, &sb); if (S_ISREG(sb.st_mode)) { /* Handle regular file */ }
3.fstat和stat的区别是:stat是从文件名出发得到文件属性信息结构体,而fstat是从一个已经打开的文件fd出发得到一个文件的属性信息。所以用的时候如果文件没有打开(我们并不想打开文件操作而只是希望得到文件属性)那就用stat,如果文件已经被打开了然后要属性那就用fstat效率会更高(stat是从磁盘去读取文件的,而fstat是从内存读取动态文件的)。
lstat和stat/fstat的差别在于:对于符号链接文件,stat和fstat查阅的是符号链接文件指向的文件的属性,而lstat查阅的是符号链接文件本身的属性。
二.文件权限有哪些,怎么看,怎么改
1.怎么看
命令行中:ls -l
打印出的权限列表
(1)123456789一共9位,3个一组。第一组三个表示文件的属主(owner、user)对该文件的可读、可写、可执行权限;第2组3个位表示文件的属主所在的组(group)对该文件的权限;第3组3个位表示其他用户(others)对该文件的权限。
(2)属主就是这个文件属于谁,一般来说文件创建时属主就是创建这个文件的那个用户。但是我们一个文件创建之后还可以用chown命令去修改一个文件的属主,还可以用chgrp命令去修改一个文件所在的组。
C程序中:st_mode位用来检查权限,宏定义如下
The following mask values are defined for the file mode component of the st_mode field: S_ISUID 04000 set-user-ID bit (see execve(2)) S_ISGID 02000 set-group-ID bit (see below) S_ISVTX 01000 sticky bit (see below) S_IRWXU 00700 owner has read, write, and execute permission S_IRUSR 00400 owner has read permission S_IWUSR 00200 owner has write permission S_IXUSR 00100 owner has execute permission S_IRWXG 00070 group has read, write, and execute permission S_IRGRP 00040 group has read permission S_IWGRP 00020 group has write permission S_IXGRP 00010 group has execute permission S_IRWXO 00007 others (not in group) have read, write, and execute permission S_IROTH 00004 others have read permission S_IWOTH 00002 others have write permission S_IXOTH 00001 others have execute permission
stat(pathname, &sb); if (sb.st_mode & S_IRUSR) { //... }
此外,还有access函数用来检查权限
int access(const char *pathname, int mode);
mode可以是R_OK,W_OK,X_OK,分别是读写和执行权限检查,有权限函数返回0,无权限返回-1
2.怎么改
chmod修改文件权限,命令行中:https://www.runoob.com/linux/linux-comm-chmod.html
C文件中:
int chmod(const char *pathname, mode_t mode);
函数返回0修改成功,返回-1修改失败
chown修改文件属主:https://www.runoob.com/linux/linux-comm-chown.html
umask用来设定系统中新创建的文件的默认权限的
mode_t umask(mode_t mask);
三.目录文件的读取
opendir与readdir函数
(1)opendir打开一个目录后得到一个DIR类型的指针给readdir使用
(2)readdir函数调用一次就会返回一个struct dirent类型的指针,这个指针指向一个结构体变量,这个结构体变量里面记录了一个目录项(所谓目录项就是目录中的一个子文件)。
(3)readdir调用一次只能读出一个目录项,要想读出目录中所有的目录项必须多次调用readdir函数。readdir函数内部户记住哪个目录项已经被读过了哪个还没读,所以多次调用后不会重复返回已经返回过的目录项。当readdir函数返回NULL时就表示目录中所有的目录项已经读完了。
例程:
#include#include #include int main(int argc, char **argv) { DIR *pDir = NULL; struct dirent * pEnt = NULL; unsigned int cnt = 0; if (argc != 2) { printf("usage: %s dirname\n", argv[0]); return -1; } pDir = opendir(argv[1]); if (NULL == pDir) { perror("opendir"); return -1; } while (1) { pEnt = readdir(pDir); if(pEnt != NULL) { // 还有子文件,在此处理子文件 printf("name:[%s] ,", pEnt->d_name); cnt++; if (pEnt->d_type == DT_REG) { printf("是普通文件\n"); } else { printf("不是普通文件\n"); } } else { break; } }; printf("总文件数为:%d\n", cnt); return 0; }
struct dirent *readdir(DIR *dirp);
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 */ };