class File::Stat
类 File::Stat 的对象封装了 File 对象的常见状态信息。这些信息是在创建 File::Stat 对象时记录的;此后对文件的更改将不会反映出来。File::Stat 对象由 IO#stat、File::stat、File#lstat 和 File::lstat 返回。其中许多方法返回特定于平台的数值,并非所有数值在所有系统上都有意义。另请参阅 Kernel#test。
Public Class Methods
Source
static VALUE
rb_stat_init(VALUE obj, VALUE fname)
{
rb_io_stat_data st;
FilePathValue(fname);
fname = rb_str_encode_ospath(fname);
if (STATX(StringValueCStr(fname), &st, STATX_ALL) == -1) {
rb_sys_fail_path(fname);
}
struct rb_stat *rb_st;
TypedData_Get_Struct(obj, struct rb_stat, &stat_data_type, rb_st);
rb_st->stat = st;
rb_st->initialized = true;
return Qnil;
}
为给定的文件名创建一个 File::Stat 对象(如果文件不存在,则引发异常)。
Public Instance Methods
Source
static VALUE
rb_stat_cmp(VALUE self, VALUE other)
{
if (rb_obj_is_kind_of(other, rb_obj_class(self))) {
stat_timestamp ts1 = statx_mtimespec(get_stat(self));
stat_timestamp ts2 = statx_mtimespec(get_stat(other));
if (ts1.tv_sec == ts2.tv_sec) {
if (ts1.tv_nsec == ts2.tv_nsec) return INT2FIX(0);
if (ts1.tv_nsec < ts2.tv_nsec) return INT2FIX(-1);
return INT2FIX(1);
}
if (ts1.tv_sec < ts2.tv_sec) return INT2FIX(-1);
return INT2FIX(1);
}
return Qnil;
}
通过比较它们的修改时间来比较 self 和 other;即,通过比较 self.mtime 和 other.mtime。
返回
-
如果
self.mtime较早,则返回-1。 -
如果两个值相等,则返回
0。 -
如果
self.mtime较晚,则返回1。 -
如果
other不是File::Stat对象,则返回nil。
示例
stat0 = File.stat('README.md') stat1 = File.stat('NEWS.md') stat0.mtime # => 2025-12-20 15:33:05.6972341 -0600 stat1.mtime # => 2025-12-20 16:02:08.2672945 -0600 stat0 <=> stat1 # => -1 stat0 <=> stat0.dup # => 0 stat1 <=> stat0 # => 1 stat0 <=> :foo # => nil
类 File::Stat 包含了模块 Comparable,该模块的每个方法都使用 File::Stat#<=> 进行比较。
Source
static VALUE
rb_stat_atime(VALUE self)
{
return stat_time(statx_atimespec(get_stat(self)));
}
将此文件的最后访问时间作为 Time 类对象返回。
File.stat("testfile").atime #=> Wed Dec 31 18:00:00 CST 1969
Source
static VALUE
rb_stat_birthtime(VALUE self)
{
return statx_birthtime(get_stat(self));
}
返回 stat 的创建时间。
如果平台不支持创建时间,则引发 NotImplementedError。
File.write("testfile", "foo") sleep 10 File.write("testfile", "bar") sleep 10 File.chmod(0644, "testfile") sleep 10 File.read("testfile") File.stat("testfile").birthtime #=> 2014-02-24 11:19:17 +0900 File.stat("testfile").mtime #=> 2014-02-24 11:19:27 +0900 File.stat("testfile").ctime #=> 2014-02-24 11:19:37 +0900 File.stat("testfile").atime #=> 2014-02-24 11:19:47 +0900
Source
static VALUE
rb_stat_blksize(VALUE self)
{
#ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
return ULONG2NUM(get_stat(self)->ST_(blksize));
#else
return Qnil;
#endif
}
返回本地文件系统的块大小。在不支持此信息的平台上将返回 nil。
File.stat("testfile").blksize #=> 4096
Source
static VALUE
rb_stat_b(VALUE obj)
{
#ifdef S_ISBLK
if (S_ISBLK(get_stat(obj)->ST_(mode))) return Qtrue;
#endif
return Qfalse;
}
如果文件是块设备,则返回 true,如果不是或操作系统不支持此功能,则返回 false。
File.stat("testfile").blockdev? #=> false File.stat("/dev/hda1").blockdev? #=> true
Source
static VALUE
rb_stat_blocks(VALUE self)
{
#ifdef HAVE_STRUCT_STAT_ST_BLOCKS
# if SIZEOF_STRUCT_STAT_ST_BLOCKS > SIZEOF_LONG
return ULL2NUM(get_stat(self)->ST_(blocks));
# else
return ULONG2NUM(get_stat(self)->ST_(blocks));
# endif
#else
return Qnil;
#endif
}
返回为该文件分配的本地文件系统块的数量,如果操作系统不支持此功能,则返回 nil。
File.stat("testfile").blocks #=> 2
Source
static VALUE
rb_stat_c(VALUE obj)
{
if (S_ISCHR(get_stat(obj)->ST_(mode))) return Qtrue;
return Qfalse;
}
如果文件是字符设备,则返回 true,如果不是或操作系统不支持此功能,则返回 false。
File.stat("/dev/tty").chardev? #=> true
Source
static VALUE
rb_stat_ctime(VALUE self)
{
return stat_time(statx_ctimespec(get_stat(self)));
}
返回 stat 的更改时间(即,目录信息更改的时间,而不是文件本身)。
请注意,在 Windows (NTFS) 上,返回的是创建时间(birth time)。
File.stat("testfile").ctime #=> Wed Apr 09 08:53:14 CDT 2003
Source
static VALUE
rb_stat_dev(VALUE self)
{
#if RUBY_USE_STATX
unsigned int m = get_stat(self)->stx_dev_major;
unsigned int n = get_stat(self)->stx_dev_minor;
return ULL2NUM(makedev(m, n));
#elif SIZEOF_STRUCT_STAT_ST_DEV <= SIZEOF_DEV_T
return DEVT2NUM(get_stat(self)->st_dev);
#elif SIZEOF_STRUCT_STAT_ST_DEV <= SIZEOF_LONG
return ULONG2NUM(get_stat(self)->st_dev);
#else
return ULL2NUM(get_stat(self)->st_dev);
#endif
}
返回一个整数,表示 stat 所在设备的编号。
File.stat("testfile").dev #=> 774
Source
static VALUE
rb_stat_dev_major(VALUE self)
{
#if RUBY_USE_STATX
return UINT2NUM(get_stat(self)->stx_dev_major);
#elif defined(major)
return UINT2NUM(major(get_stat(self)->st_dev));
#else
return Qnil;
#endif
}
返回 File_Stat#dev 的主设备号,或 nil。
File.stat("/dev/fd1").dev_major #=> 2 File.stat("/dev/tty").dev_major #=> 5
Source
static VALUE
rb_stat_dev_minor(VALUE self)
{
#if RUBY_USE_STATX
return UINT2NUM(get_stat(self)->stx_dev_minor);
#elif defined(minor)
return UINT2NUM(minor(get_stat(self)->st_dev));
#else
return Qnil;
#endif
}
返回 File_Stat#dev 的次设备号,或 nil。
File.stat("/dev/fd1").dev_minor #=> 1 File.stat("/dev/tty").dev_minor #=> 0
Source
static VALUE
rb_stat_d(VALUE obj)
{
if (S_ISDIR(get_stat(obj)->ST_(mode))) return Qtrue;
return Qfalse;
}
如果 stat 是目录,则返回 true,否则返回 false。
File.stat("testfile").directory? #=> false File.stat(".").directory? #=> true
Source
static VALUE
rb_stat_x(VALUE obj)
{
rb_io_stat_data *st = get_stat(obj);
#ifdef USE_GETEUID
if (geteuid() == 0) {
return RBOOL(st->ST_(mode) & S_IXUGO);
}
#endif
#ifdef S_IXUSR
if (rb_stat_owned(obj))
return RBOOL(st->ST_(mode) & S_IXUSR);
#endif
#ifdef S_IXGRP
if (rb_stat_grpowned(obj))
return RBOOL(st->ST_(mode) & S_IXGRP);
#endif
#ifdef S_IXOTH
if (!(st->ST_(mode) & S_IXOTH)) return Qfalse;
#endif
return Qtrue;
}
如果 stat 是可执行文件,或者操作系统不区分可执行文件和不可执行文件,则返回 true。测试使用进程的有效所有者。
File.stat("testfile").executable? #=> false
Source
static VALUE
rb_stat_X(VALUE obj)
{
rb_io_stat_data *st = get_stat(obj);
#ifdef USE_GETEUID
if (getuid() == 0) {
return RBOOL(st->ST_(mode) & S_IXUGO);
}
#endif
#ifdef S_IXUSR
if (rb_stat_rowned(obj))
return RBOOL(st->ST_(mode) & S_IXUSR);
#endif
#ifdef S_IXGRP
if (rb_group_member(get_stat(obj)->ST_(gid)))
return RBOOL(st->ST_(mode) & S_IXGRP);
#endif
#ifdef S_IXOTH
if (!(st->ST_(mode) & S_IXOTH)) return Qfalse;
#endif
return Qtrue;
}
与 executable? 相同,但使用进程的真实所有者进行测试。
Source
static VALUE
rb_stat_f(VALUE obj)
{
if (S_ISREG(get_stat(obj)->ST_(mode))) return Qtrue;
return Qfalse;
}
如果 stat 是常规文件(而不是设备文件、管道、套接字等),则返回 true。
File.stat("testfile").file? #=> true
Source
static VALUE
rb_stat_ftype(VALUE obj)
{
return rb_file_ftype(get_stat(obj)->ST_(mode));
}
标识 stat 的类型。返回的字符串是以下之一:“file”、“directory”、“characterSpecial”、“blockSpecial”、“fifo”、“link”、“socket”或“unknown”。
File.stat("/dev/tty").ftype #=> "characterSpecial"
Source
static VALUE
rb_stat_gid(VALUE self)
{
return GIDT2NUM(get_stat(self)->ST_(gid));
}
返回 stat 所有者的数字组 ID。
File.stat("testfile").gid #=> 500
Source
static VALUE
rb_stat_grpowned(VALUE obj)
{
#ifndef _WIN32
if (rb_group_member(get_stat(obj)->ST_(gid))) return Qtrue;
#endif
return Qfalse;
}
如果进程的有效组 ID 与 stat 的组 ID 相同,则返回 true。在 Windows 上,返回 false。
File.stat("testfile").grpowned? #=> true File.stat("/etc/passwd").grpowned? #=> false
Source
static VALUE
rb_stat_ino(VALUE self)
{
rb_io_stat_data *ptr = get_stat(self);
#ifdef HAVE_STRUCT_STAT_ST_INOHIGH
/* assume INTEGER_PACK_LSWORD_FIRST and st_inohigh is just next of st_ino */
return rb_integer_unpack(&ptr->st_ino, 2,
SIZEOF_STRUCT_STAT_ST_INO, 0,
INTEGER_PACK_LSWORD_FIRST|INTEGER_PACK_NATIVE_BYTE_ORDER|
INTEGER_PACK_2COMP);
#else
return UIANY2NUM(ptr->ST_(ino));
#endif
}
返回 stat 的 inode 号。
File.stat("testfile").ino #=> 1083669
Source
static VALUE
rb_stat_inspect(VALUE self)
{
VALUE str;
size_t i;
static const struct {
const char *name;
VALUE (*func)(VALUE);
} member[] = {
{"dev", rb_stat_dev},
{"ino", rb_stat_ino},
{"mode", rb_stat_mode},
{"nlink", rb_stat_nlink},
{"uid", rb_stat_uid},
{"gid", rb_stat_gid},
{"rdev", rb_stat_rdev},
{"size", rb_stat_size},
{"blksize", rb_stat_blksize},
{"blocks", rb_stat_blocks},
{"atime", rb_stat_atime},
{"mtime", rb_stat_mtime},
{"ctime", rb_stat_ctime},
#if defined(HAVE_STRUCT_STAT_ST_BIRTHTIMESPEC)
{"birthtime", rb_stat_birthtime},
#endif
};
struct rb_stat* rb_st;
TypedData_Get_Struct(self, struct rb_stat, &stat_data_type, rb_st);
if (!rb_st->initialized) {
return rb_sprintf("#<%s: uninitialized>", rb_obj_classname(self));
}
str = rb_str_buf_new2("#<");
rb_str_buf_cat2(str, rb_obj_classname(self));
rb_str_buf_cat2(str, " ");
for (i = 0; i < sizeof(member)/sizeof(member[0]); i++) {
VALUE v;
if (i > 0) {
rb_str_buf_cat2(str, ", ");
}
rb_str_buf_cat2(str, member[i].name);
rb_str_buf_cat2(str, "=");
v = (*member[i].func)(self);
if (i == 2) { /* mode */
rb_str_catf(str, "0%lo", (unsigned long)NUM2ULONG(v));
}
else if (i == 0 || i == 6) { /* dev/rdev */
rb_str_catf(str, "0x%"PRI_DEVT_PREFIX"x", NUM2DEVT(v));
}
else {
rb_str_append(str, rb_inspect(v));
}
}
rb_str_buf_cat2(str, ">");
return str;
}
为 stat 生成格式良好的描述。
File.stat("/etc/passwd").inspect #=> "#<File::Stat dev=0xe000005, ino=1078078, mode=0100644, # nlink=1, uid=0, gid=0, rdev=0x0, size=1374, blksize=4096, # blocks=8, atime=Wed Dec 10 10:16:12 CST 2003, # mtime=Fri Sep 12 15:41:41 CDT 2003, # ctime=Mon Oct 27 11:20:27 CST 2003, # birthtime=Mon Aug 04 08:13:49 CDT 2003>"
Source
static VALUE
rb_stat_mode(VALUE self)
{
return UINT2NUM(ST2UINT(get_stat(self)->ST_(mode)));
}
返回一个整数,表示 stat 的权限位。这些位的含义取决于平台;在 Unix 系统上,请参阅 stat(2)。
File.chmod(0644, "testfile") #=> 1 s = File.stat("testfile") sprintf("%o", s.mode) #=> "100644"
Source
static VALUE
rb_stat_mtime(VALUE self)
{
return stat_time(statx_mtimespec(get_stat(self)));
}
返回 stat 的修改时间。
File.stat("testfile").mtime #=> Wed Apr 09 08:53:14 CDT 2003
Source
static VALUE
rb_stat_nlink(VALUE self)
{
/* struct stat::st_nlink is nlink_t in POSIX. Not the case for Windows. */
const rb_io_stat_data *ptr = get_stat(self);
return UIANY2NUM(ptr->ST_(nlink));
}
返回 stat 的硬链接数。
File.stat("testfile").nlink #=> 1 File.link("testfile", "testfile.bak") #=> 0 File.stat("testfile").nlink #=> 2
Source
static VALUE
rb_stat_owned(VALUE obj)
{
if (get_stat(obj)->ST_(uid) == geteuid()) return Qtrue;
return Qfalse;
}
如果进程的有效用户 ID 与 stat 的所有者相同,则返回 true。
File.stat("testfile").owned? #=> true File.stat("/etc/passwd").owned? #=> false
Source
static VALUE
rb_stat_p(VALUE obj)
{
#ifdef S_IFIFO
if (S_ISFIFO(get_stat(obj)->ST_(mode))) return Qtrue;
#endif
return Qfalse;
}
如果操作系统支持管道且 stat 是管道,则返回 true;否则返回 false。
Source
static VALUE
rb_stat_rdev(VALUE self)
{
#if RUBY_USE_STATX
unsigned int m = get_stat(self)->stx_rdev_major;
unsigned int n = get_stat(self)->stx_rdev_minor;
return ULL2NUM(makedev(m, n));
#elif !defined(HAVE_STRUCT_STAT_ST_RDEV)
return Qnil;
#elif SIZEOF_STRUCT_STAT_ST_RDEV <= SIZEOF_DEV_T
return DEVT2NUM(get_stat(self)->ST_(rdev));
#elif SIZEOF_STRUCT_STAT_ST_RDEV <= SIZEOF_LONG
return ULONG2NUM(get_stat(self)->ST_(rdev));
#else
return ULL2NUM(get_stat(self)->ST_(rdev));
#endif
}
返回一个整数,表示 stat 所在设备的类型。如果操作系统不支持此功能,则返回 nil。
File.stat("/dev/fd1").rdev #=> 513 File.stat("/dev/tty").rdev #=> 1280
Source
static VALUE
rb_stat_rdev_major(VALUE self)
{
#if RUBY_USE_STATX
return UINT2NUM(get_stat(self)->stx_rdev_major);
#elif defined(HAVE_STRUCT_STAT_ST_RDEV) && defined(major)
return UINT2NUM(major(get_stat(self)->ST_(rdev)));
#else
return Qnil;
#endif
}
返回 File_Stat#rdev 的主设备号,或 nil。
File.stat("/dev/fd1").rdev_major #=> 2 File.stat("/dev/tty").rdev_major #=> 5
Source
static VALUE
rb_stat_rdev_minor(VALUE self)
{
#if RUBY_USE_STATX
return UINT2NUM(get_stat(self)->stx_rdev_minor);
#elif defined(HAVE_STRUCT_STAT_ST_RDEV) && defined(minor)
return UINT2NUM(minor(get_stat(self)->ST_(rdev)));
#else
return Qnil;
#endif
}
返回 File_Stat#rdev 的次设备号,或 nil。
File.stat("/dev/fd1").rdev_minor #=> 1 File.stat("/dev/tty").rdev_minor #=> 0
Source
static VALUE
rb_stat_r(VALUE obj)
{
rb_io_stat_data *st = get_stat(obj);
#ifdef USE_GETEUID
if (geteuid() == 0) return Qtrue;
#endif
#ifdef S_IRUSR
if (rb_stat_owned(obj))
return RBOOL(st->ST_(mode) & S_IRUSR);
#endif
#ifdef S_IRGRP
if (rb_stat_grpowned(obj))
return RBOOL(st->ST_(mode) & S_IRGRP);
#endif
#ifdef S_IROTH
if (!(st->ST_(mode) & S_IROTH)) return Qfalse;
#endif
return Qtrue;
}
如果此进程的有效用户 ID 可以读取 stat,则返回 true。
File.stat("testfile").readable? #=> true
Source
static VALUE
rb_stat_R(VALUE obj)
{
rb_io_stat_data *st = get_stat(obj);
#ifdef USE_GETEUID
if (getuid() == 0) return Qtrue;
#endif
#ifdef S_IRUSR
if (rb_stat_rowned(obj))
return RBOOL(st->ST_(mode) & S_IRUSR);
#endif
#ifdef S_IRGRP
if (rb_group_member(get_stat(obj)->ST_(gid)))
return RBOOL(st->ST_(mode) & S_IRGRP);
#endif
#ifdef S_IROTH
if (!(st->ST_(mode) & S_IROTH)) return Qfalse;
#endif
return Qtrue;
}
如果此进程的真实用户 ID 可以读取 stat,则返回 true。
File.stat("testfile").readable_real? #=> true
Source
static VALUE
rb_stat_sgid(VALUE obj)
{
#ifdef S_ISGID
if (get_stat(obj)->ST_(mode) & S_ISGID) return Qtrue;
#endif
return Qfalse;
}
如果 stat 设置了 set-group-id 权限位,则返回 true,否则返回 false;如果操作系统不支持此功能,也返回 false。
File.stat("/usr/sbin/lpc").setgid? #=> true
Source
static VALUE
rb_stat_suid(VALUE obj)
{
#ifdef S_ISUID
if (get_stat(obj)->ST_(mode) & S_ISUID) return Qtrue;
#endif
return Qfalse;
}
如果 stat 设置了 set-user-id 权限位,则返回 true,否则返回 false;如果操作系统不支持此功能,也返回 false。
File.stat("/bin/su").setuid? #=> true
Source
static VALUE
rb_stat_size(VALUE self)
{
return OFFT2NUM(get_stat(self)->ST_(size));
}
返回 stat 的大小(以字节为单位)。
File.stat("testfile").size #=> 66
Source
static VALUE
rb_stat_s(VALUE obj)
{
rb_off_t size = get_stat(obj)->ST_(size);
if (size == 0) return Qnil;
return OFFT2NUM(size);
}
如果 stat 是零长度文件,则返回 nil,否则返回文件的大小。
File.stat("testfile").size? #=> 66 File.stat(File::NULL).size? #=> nil
Source
static VALUE
rb_stat_S(VALUE obj)
{
#ifdef S_ISSOCK
if (S_ISSOCK(get_stat(obj)->ST_(mode))) return Qtrue;
#endif
return Qfalse;
}
如果 stat 是套接字,则返回 true,如果不是或操作系统不支持此功能,则返回 false。
File.stat("testfile").socket? #=> false
Source
static VALUE
rb_stat_sticky(VALUE obj)
{
#ifdef S_ISVTX
if (get_stat(obj)->ST_(mode) & S_ISVTX) return Qtrue;
#endif
return Qfalse;
}
如果 stat 设置了 sticky 位,则返回 true,否则返回 false;如果操作系统不支持此功能,也返回 false。
File.stat("testfile").sticky? #=> false
Source
static VALUE
rb_stat_l(VALUE obj)
{
#ifdef S_ISLNK
if (S_ISLNK(get_stat(obj)->ST_(mode))) return Qtrue;
#endif
return Qfalse;
}
如果 stat 是符号链接,则返回 true,如果不是或操作系统不支持此功能,则返回 false。由于 File::stat 会自动跟随符号链接,因此由 File::stat 返回的对象,其 symlink? 始终为 false。
File.symlink("testfile", "alink") #=> 0 File.stat("alink").symlink? #=> false File.lstat("alink").symlink? #=> true
Source
static VALUE
rb_stat_uid(VALUE self)
{
return UIDT2NUM(get_stat(self)->ST_(uid));
}
返回 stat 所有者的数字用户 ID。
File.stat("testfile").uid #=> 501
Source
static VALUE
rb_stat_wr(VALUE obj)
{
#ifdef S_IROTH
rb_io_stat_data *st = get_stat(obj);
if ((st->ST_(mode) & (S_IROTH)) == S_IROTH) {
return UINT2NUM(st->ST_(mode) & (S_IRUGO|S_IWUGO|S_IXUGO));
}
#endif
return Qnil;
}
如果 stat 可被其他人读取,则返回一个整数,表示 stat 的文件权限位。否则返回 nil。这些位的含义取决于平台;在 Unix 系统上,请参阅 stat(2)。
m = File.stat("/etc/passwd").world_readable? #=> 420 sprintf("%o", m) #=> "644"
Source
static VALUE
rb_stat_ww(VALUE obj)
{
#ifdef S_IWOTH
rb_io_stat_data *st = get_stat(obj);
if ((st->ST_(mode) & (S_IWOTH)) == S_IWOTH) {
return UINT2NUM(st->ST_(mode) & (S_IRUGO|S_IWUGO|S_IXUGO));
}
#endif
return Qnil;
}
如果 stat 可被其他人写入,则返回一个整数,表示 stat 的文件权限位。否则返回 nil。这些位的含义取决于平台;在 Unix 系统上,请参阅 stat(2)。
m = File.stat("/tmp").world_writable? #=> 511 sprintf("%o", m) #=> "777"
Source
static VALUE
rb_stat_w(VALUE obj)
{
rb_io_stat_data *st = get_stat(obj);
#ifdef USE_GETEUID
if (geteuid() == 0) return Qtrue;
#endif
#ifdef S_IWUSR
if (rb_stat_owned(obj))
return RBOOL(st->ST_(mode) & S_IWUSR);
#endif
#ifdef S_IWGRP
if (rb_stat_grpowned(obj))
return RBOOL(st->ST_(mode) & S_IWGRP);
#endif
#ifdef S_IWOTH
if (!(st->ST_(mode) & S_IWOTH)) return Qfalse;
#endif
return Qtrue;
}
如果此进程的有效用户 ID 可以写入 stat,则返回 true。
File.stat("testfile").writable? #=> true
Source
static VALUE
rb_stat_W(VALUE obj)
{
rb_io_stat_data *st = get_stat(obj);
#ifdef USE_GETEUID
if (getuid() == 0) return Qtrue;
#endif
#ifdef S_IWUSR
if (rb_stat_rowned(obj))
return RBOOL(st->ST_(mode) & S_IWUSR);
#endif
#ifdef S_IWGRP
if (rb_group_member(get_stat(obj)->ST_(gid)))
return RBOOL(st->ST_(mode) & S_IWGRP);
#endif
#ifdef S_IWOTH
if (!(st->ST_(mode) & S_IWOTH)) return Qfalse;
#endif
return Qtrue;
}
如果此进程的真实用户 ID 可以写入 stat,则返回 true。
File.stat("testfile").writable_real? #=> true
Source
static VALUE
rb_stat_z(VALUE obj)
{
if (get_stat(obj)->ST_(size) == 0) return Qtrue;
return Qfalse;
}
如果 stat 是一个零长度文件,则返回 true;否则返回 false。
File.stat("testfile").zero? #=> false