ls 或 stat 这样的命令如何区分文件类型,对象是文件还是目录?
例如,我创建了这两个对象,考虑到目录也是文件这一事实......具有一些特殊规则,我想知道如何在命令的输出中将stat
它们标记为“目录”和“常规空文件” ”。
$ mkdir testdir;touch testfile
$ stat testdir | head -2;stat testfile | head -2
File: `testdir'
Size: 4096 Blocks: 8 IO Block: 4096 directory
File: `testfile'
Size: 0 Blocks: 0 IO Block: 4096 regular empty file
后来我在分别执行目录testdir和文件testfile的stat时做了strace。在跟踪输出中我注意到这些
lstat("testdir/", {st_mode=S_IFDIR|0775, st_size=4096, ...}) = 0
和
lstat("testfile", {st_mode=S_IFREG|0664, st_size=0, ...}) = 0
有人请告诉我如何st_mode
获取这些值S_IFDIR
和S_IFREG
。
我可能听起来很困惑;我确实是。
答案1
让我们尝试消除您的困惑。在inode
st_mode 中,有一个由 stat/lstat(和 64 位变体)返回的 16 位字段。其中 9 位用于 rwxrwxrwx 权限,另外 3 位用于sticky bit
,set group id (sgid) bit
和set userid (suid) bit
。其他 4 位用于编码一些类型信息。这可以说它是一个常规文件、目录、块或字符设备、命名管道等。
因此,如果您创建一个目录,那么这 4 位表示它是一个目录。您可以在 strace 输出中看到这一点...
lstat("testdir/", {st_mode=S_IFDIR|0775, st_size=4096, ...})
^^^^^^^ 4 bits showing the type is directory
^ 3 bits (this is octal) for suid/sgid/sticky
^^^ rwxrwxrwx info.
答案2
命令ls
,stat
甚至file
在内部使用 Cstat()
系统调用来收集详细信息。这里定义了结构。如果您检查统计文件:
/usr/include/bits/stat.h
/usr/include/linux/stat.h
定义了以下位:
/* Encoding of the file mode. */
#define __S_IFMT 0170000 /* These bits determine file type. */
/* File types. */
#define __S_IFDIR 0040000 /* Directory. */
#define __S_IFCHR 0020000 /* Character device. */
#define __S_IFBLK 0060000 /* Block device. */
#define __S_IFREG 0100000 /* Regular file. */
#define __S_IFIFO 0010000 /* FIFO. */
#define __S_IFLNK 0120000 /* Symbolic link. */
#define __S_IFSOCK 0140000 /* Socket. */
the stat function will check the POSIX macros and compare to see if it is a regular file/ directory
#define S_ISLNK(m) (((m) & S_IFMT) == S_IFLNK)
#define S_ISREG(m) (((m) & S_IFMT) == S_IFREG)
#define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
#define S_ISCHR(m) (((m) & S_IFMT) == S_IFCHR)
#define S_ISBLK(m) (((m) & S_IFMT) == S_IFBLK)
#define S_ISFIFO(m) (((m) & S_IFMT) == S_IFIFO)
#define S_ISSOCK(m) (((m) & S_IFMT) == S_IFSOCK)
这就是st_mode
获取这些值S_IFDIR
和 的方式S_IFREG
。
仅供参考...现在关于 inode 如何识别文件类型的一个主要问题是:
对于XFS文件系统,inode数据结构分为3部分:
di_core
(96 字节)di_u
数据分叉di_a
扩展属性叉
核心包含索引节点所代表的内容、统计数据以及描述数据和属性分支的信息。这里的文件类型由di_core.di_mode
(例如常规文件、目录、链接等)控制。
“数据di_u
叉”包含与索引节点相关的正常数据。
“属性di_a
叉”包含扩展属性。