ls 或 stat 等命令如何区分文件类型?

ls 或 stat 等命令如何区分文件类型?

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_IFDIRS_IFREG

我可能听起来很困惑;我确实是。

答案1

让我们尝试消除您的困惑。在inodest_mode 中,有一个由 stat/lstat(和 64 位变体)返回的 16 位字段。其中 9 位用于 rwxrwxrwx 权限,另外 3 位用于sticky bit,set group id (sgid) bitset 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

命令lsstat甚至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叉”包含扩展属性。

相关内容