Class: File::Stat
| Relationships & Source Files | |
| Super Chains via Extension / Inclusion / Inheritance | |
|
Instance Chain:
self,
::Comparable
|
|
| Inherits: | Object |
| Defined in: | file.c, file.c |
Overview
A File::Stat object contains information about an entry in the file system.
Each of these methods returns a new File::Stat object:
Snapshot
A new File::Stat object takes an immediate "snapshot" of the entry's information; the captured information is never updated, regardless of changes in the actual entry:
The entry must exist when .new is called:
filepath = 't.tmp'
File.exist?(filepath) # => false
File::Stat.new(filepath) # Raises Errno::ENOENT: No such file or directory.
File.write(filepath, 'foo') # Create the file.
stat = File::Stat.new(filepath) # Okay.
Later changes to the actual entry do not change the File::Stat object:
File.atime(filepath) # => 2026-04-01 11:51:38.0014518 -0500
stat.atime # => 2026-04-01 11:51:38.0014518 -0500
File.write(filepath, 'bar')
File.atime(filepath) # => 2026-04-01 11:58:11.922614 -0500
stat.atime # => 2026-04-01 11:51:38.0014518 -0500
File.delete(filepath)
stat.atime # => 2026-04-01 11:51:38.0014518 -0500
OS-Dependencies
Methods in a File::Stat object may return platform-dependents values,
and not all values are meaningful on all systems;
for example, #blocks returns nil on Windows,
but returns an integer on Linux.
See also Kernel.test.
Class Method Summary
-
.new(file_name) ⇒ Stat
constructor
Create a
Statobject for the given file name (raising an exception if the file doesn't exist).
Instance Attribute Summary
-
#blockdev? ⇒ Boolean
readonly
Returns
trueif the file is a block device,falseif it isn't or if the operating system doesn't support this feature. -
#chardev? ⇒ Boolean
readonly
Returns
trueif the file is a character device,falseif it isn't or if the operating system doesn't support this feature. -
#directory? ⇒ Boolean
readonly
Returns
trueif stat is a directory,falseotherwise. -
#executable? ⇒ Boolean
readonly
Returns whether the filesystem entry represented by
selfexists and is executable; raisesErrno::ENOENTif the entry does not exist. -
#executable_real? ⇒ Boolean
readonly
Same as #executable?, but tests using the real owner of the process.
-
#file? ⇒ Boolean
readonly
Returns whether
selfrepresents a filesystem entry that exists and is a regular file; see ftype: -
#grpowned?(path) ⇒ Boolean
readonly
Returns whether the filesystem entry for the given string path exists, and the effective group id of the calling process is the owner of the entry:
-
#owned? ⇒ Boolean
readonly
Returns
trueif the effective user id of the process is the same as the owner of stat. -
#pipe? ⇒ Boolean
readonly
Returns
trueif the operating system supports pipes and stat is a pipe;falseotherwise. -
#readable? ⇒ Boolean
readonly
Returns
trueif stat is readable by the effective user id of this process. -
#readable_real? ⇒ Boolean
readonly
Returns
trueif stat is readable by the real user id of this process. -
#setgid? ⇒ Boolean
readonly
Returns
trueif stat has the set-group-id permission bit set,falseif it doesn't or if the operating system doesn't support this feature. -
#setuid? ⇒ Boolean
readonly
Returns
trueif stat has the set-user-id permission bit set,falseif it doesn't or if the operating system doesn't support this feature. -
#size ⇒ Integer
readonly
Returns the size of stat in bytes.
-
#size? ⇒ Boolean
readonly
Returns
nilif stat is a zero-length file, the size of the file otherwise. -
#socket? ⇒ Boolean
readonly
Returns
trueif stat is a socket,falseif it isn't or if the operating system doesn't support this feature. -
#sticky? ⇒ Boolean
readonly
Returns
trueif stat has its sticky bit set,falseif it doesn't or if the operating system doesn't support this feature. -
#symlink? ⇒ Boolean
readonly
Returns whether the entry in
selfis a symbolic link: -
#world_readable? ⇒ Boolean
readonly
If stat is readable by others, returns an integer representing the file permission bits of stat.
-
#world_writable? ⇒ Boolean
readonly
If stat is writable by others, returns an integer representing the file permission bits of stat.
-
#writable? ⇒ Boolean
readonly
Returns
trueif stat is writable by the effective user id of this process. -
#writable_real? ⇒ Boolean
readonly
Returns
trueif stat is writable by the real user id of this process. -
#zero? ⇒ Boolean
readonly
Returns
trueif stat is a zero-length file;falseotherwise.
Instance Method Summary
-
#<=>(other) ⇒ 1, ...
Compares
selfandother, by comparing their modification times; that is, by comparing self.mtime and other.mtime. - #atime ⇒ Time
- #birthtime ⇒ Time
-
#blksize ⇒ Integer?
Returns the native file system's block size.
-
#blocks ⇒ Integer?
Returns the number of native file system blocks allocated for this file, or
nilif the operating system doesn't support this feature. -
#ctime ⇒ Time
Returns the change time for stat (that is, the time directory information about the file was changed, not the file itself).
-
#dev ⇒ Integer
Returns an integer representing the device on which stat resides.
-
#dev_major ⇒ Integer
Returns the major part of
File_Stat#devornil. -
#dev_minor ⇒ Integer
Returns the minor part of
File_Stat#devornil. -
#ftype ⇒ String
Returns the string type of the object at path, one of:
-
#gid ⇒ Integer
Returns the numeric group id of the owner of stat.
-
#ino ⇒ Integer
Returns the inode number for stat.
-
#inspect ⇒ String
Produce a nicely formatted description of stat.
-
#mode ⇒ Integer
Returns an integer representing the permission bits of stat.
-
#mtime ⇒ Time
Returns the modification time of stat.
-
#nlink ⇒ Integer
Returns the number of hard links to stat.
-
#rdev ⇒ Integer?
Returns an integer representing the device type on which stat resides.
-
#rdev_major ⇒ Integer
Returns the major part of
File_Stat#rdevornil. -
#rdev_minor ⇒ Integer
Returns the minor part of
File_Stat#rdevornil. -
#uid ⇒ Integer
Returns the numeric user id of the owner of stat.
- #initialize_copy(orig) Internal use only
::Comparable - Included
| #< | Returns whether |
| #<= | Returns whether |
| #== | Compares two objects based on the receiver's #<=> method, returning true if it returns 0. |
| #> | Returns whether |
| #>= | Returns whether |
| #between? | |
| #clamp |
Constructor Details
.new(file_name) ⇒ Stat
Create a Stat object for the given file name (raising an
exception if the file doesn't exist).
# File 'file.c', line 6587
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;
}
Instance Attribute Details
#blockdev? ⇒ Boolean (readonly)
# File 'file.c', line 6768
static VALUE
rb_stat_b(VALUE obj)
{
#ifdef S_ISBLK
if (S_ISBLK(get_stat(obj)->ST_(mode))) return Qtrue;
#endif
return Qfalse;
}
#chardev? ⇒ Boolean (readonly)
# File 'file.c', line 6790
static VALUE
rb_stat_c(VALUE obj)
{
if (S_ISCHR(get_stat(obj)->ST_(mode))) return Qtrue;
return Qfalse;
}
#directory? ⇒ Boolean (readonly)
Returns true if stat is a directory,
false otherwise.
File.stat("testfile").directory? #=> false
File.stat(".").directory? #=> true
# File 'file.c', line 6677
static VALUE
rb_stat_d(VALUE obj)
{
if (S_ISDIR(get_stat(obj)->ST_(mode))) return Qtrue;
return Qfalse;
}
#executable? ⇒ Boolean (readonly)
Returns whether the filesystem entry represented by self
exists and is executable;
raises Errno::ENOENT if the entry does not exist.
On Windows, the entry is executable if its path has file extension
.bat, .cmd, .com, or .exe:
File.stat('win32/rtname.cmd').executable? # => true
File.stat('win32/file.c').executable? # => false
On other systems, the entry is executable if it has the execute/search permission for the effective user and group id of the current process; see Permissions.
These examples use a helper method, #mode, that displays a mode both in octal digits and in characters:
File.stat('.').executable? # => true
mode('.') # => "040775 drwxrwxr-x"
File.stat('bin/gem').executable? # => true
mode('bin/gem') # => "100775 -rwxrwxr-x"
File.stat('/etc/passwd').executable? # => false
mode('/etc/passwd') # => "100644 -rw-r--r--"
Note that some filesystem settings may cause this method to return true
even though the entry is not executable by the effective user/group.
# File 'file.c', line 7064
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;
}
#executable_real? ⇒ Boolean (readonly)
Same as #executable?, but tests using the real owner of the process.
# File 'file.c', line 7096
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;
}
#file? ⇒ Boolean (readonly)
# File 'file.c', line 7135
static VALUE
rb_stat_f(VALUE obj)
{
if (S_ISREG(get_stat(obj)->ST_(mode))) return Qtrue;
return Qfalse;
}
#grpowned?(path) ⇒ Boolean (readonly)
Returns whether the filesystem entry for the given string File.path exists, and the effective group id of the calling process is the owner of the entry:
File.stat('README.md').grpowned? # => true
File.stat('lib').grpowned? # => true
File.stat('/etc/passwd').grpowned? # => false
Raises an exception if there is no entry at the given File.path.
Returns false on Windows.
# File 'file.c', line 6840
static VALUE
rb_stat_grpowned(VALUE obj)
{
#ifndef _WIN32
if (rb_group_member(get_stat(obj)->ST_(gid))) return Qtrue;
#endif
return Qfalse;
}
#owned? ⇒ Boolean (readonly)
# File 'file.c', line 6810
static VALUE
rb_stat_owned(VALUE obj)
{
if (get_stat(obj)->ST_(uid) == geteuid()) return Qtrue;
return Qfalse;
}
#pipe? ⇒ Boolean (readonly)
Returns true if the operating system supports pipes and
stat is a pipe; false otherwise.
# File 'file.c', line 6692
static VALUE
rb_stat_p(VALUE obj)
{
#ifdef S_IFIFO
if (S_ISFIFO(get_stat(obj)->ST_(mode))) return Qtrue;
#endif
return Qfalse;
}
#readable? ⇒ Boolean (readonly)
# File 'file.c', line 6860
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;
}
#readable_real? ⇒ Boolean (readonly)
Returns true if stat is readable by the real
user id of this process.
File.stat("testfile").readable_real? #=> true
# File 'file.c', line 6893
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;
}
#setgid? ⇒ Boolean (readonly)
# File 'file.c', line 7213
static VALUE
rb_stat_sgid(VALUE obj)
{
#ifdef S_ISGID
if (get_stat(obj)->ST_(mode) & S_ISGID) return Qtrue;
#endif
return Qfalse;
}
#setuid? ⇒ Boolean (readonly)
# File 'file.c', line 7192
static VALUE
rb_stat_suid(VALUE obj)
{
#ifdef S_ISUID
if (get_stat(obj)->ST_(mode) & S_ISUID) return Qtrue;
#endif
return Qfalse;
}
#size ⇒ Integer (readonly)
[ GitHub ]# File 'file.c', line 946
static VALUE
rb_stat_size(VALUE self)
{
return OFFT2NUM(get_stat(self)->ST_(size));
}
#size? ⇒ Boolean (readonly)
# File 'file.c', line 7172
static VALUE
rb_stat_s(VALUE obj)
{
rb_off_t size = get_stat(obj)->ST_(size);
if (size == 0) return Qnil;
return OFFT2NUM(size);
}
#socket? ⇒ Boolean (readonly)
# File 'file.c', line 6745
static VALUE
rb_stat_S(VALUE obj)
{
#ifdef S_ISSOCK
if (S_ISSOCK(get_stat(obj)->ST_(mode))) return Qtrue;
#endif
return Qfalse;
}
#sticky? ⇒ Boolean (readonly)
# File 'file.c', line 7234
static VALUE
rb_stat_sticky(VALUE obj)
{
#ifdef S_ISVTX
if (get_stat(obj)->ST_(mode) & S_ISVTX) return Qtrue;
#endif
return Qfalse;
}
#symlink? ⇒ Boolean (readonly)
Returns whether the entry in self is a symbolic link:
path = 'doc/t.tmp'
link_path = 'lib/u.tmp'
File.write(path, 'foo')
File.symlink(path, link_path)
File.stat(path).symlink? # => false
File.stat(link_path).symlink? # Raises Errno::ENOENT; entry is not a file.
File.lstat(link_path).symlink? # => true
File.delete(path)
File.delete(link_path)
# File 'file.c', line 6724
static VALUE
rb_stat_l(VALUE obj)
{
#ifdef S_ISLNK
if (S_ISLNK(get_stat(obj)->ST_(mode))) return Qtrue;
#endif
return Qfalse;
}
#world_readable? ⇒ Boolean (readonly)
If stat is readable by others, returns an integer
representing the file permission bits of stat. Returns
nil otherwise. The meaning of the bits is platform
dependent; on Unix systems, see stat(2).
m = File.stat("/etc/passwd").world_readable? #=> 420
sprintf("%o", m) #=> "644"
# File 'file.c', line 6928
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;
}
#world_writable? ⇒ Boolean (readonly)
If stat is writable by others, returns an integer
representing the file permission bits of stat. Returns
nil otherwise. The meaning of the bits is platform
dependent; on Unix systems, see stat(2).
m = File.stat("/tmp").world_writable? #=> 511
sprintf("%o", m) #=> "777"
# File 'file.c', line 7019
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;
}
#writable? ⇒ Boolean (readonly)
# File 'file.c', line 6951
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;
}
#writable_real? ⇒ Boolean (readonly)
Returns true if stat is writable by the real
user id of this process.
File.stat("testfile").writable_real? #=> true
# File 'file.c', line 6984
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;
}
#zero? ⇒ Boolean (readonly)
[ GitHub ]
# File 'file.c', line 7153
static VALUE
rb_stat_z(VALUE obj)
{
if (get_stat(obj)->ST_(size) == 0) return Qtrue;
return Qfalse;
}
Instance Method Details
#<=>(other) ⇒ 1, ...
Compares self and other, by comparing their modification times;
that is, by comparing self.mtime and other.mtime.
Returns:
-1, if self.mtime is earlier.0, if the two values are equal.1, if self.mtime is later.nil, ifotheris not aStatobject.
Examples:
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
Class File::Stat includes module ::Comparable,
each of whose methods uses <=> for comparison.
# File 'file.c', line 663
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;
}
#atime ⇒ Time
Returns a new ::Time object containing the access time
of the object represented by self
at the time self was created;
see Snapshot.
See File System Timestamps.
Access time for a file is established when it is created, and may be updated when the file content is read:
filepath = 't.tmp'
File.exist?(filepath) # => false
file = File.open(filepath, 'w+') # Create by writing; establishes access time.
file.atime # => 2026-08-14 11:55:55.436283939 -0500
stat0 = File::Stat.new(filepath) # Take snapshot.
stat0.atime # => 2026-08-14 11:55:55.436283939 -0500
file.read # Read file content; updates file access time.
file.atime # => 2026-08-14 11:56:22.74241085 -0500
stat0.atime # => 2026-08-14 11:55:55.436283939 -0500 # Not updated.
stat1 = File::Stat.new(filepath) # Take new snapshot.
stat1.atime # => 2026-08-14 11:56:22.74241085 -0500 # Updated.
# Clean up.
file.close
File.delete(filepath)
Access time for a directory is established when it is created, and may be updated when its entries are read:
dirpath = 'foo'
File.exist?(dirpath) # => false
FileUtils.cp_r('doc', 'foo') # Create directory by copying.
File.atime(dirpath) # => 2026-08-15 14:10:04.832180372 -0500
stat = File::Stat.new(dirpath)
stat.atime # => 2026-08-15 14:10:04.832180372 -0500
# Clean up.
FileUtils.rm_rf(dirpath)
dir.close
# File 'file.c', line 1152
static VALUE
rb_stat_atime(VALUE self)
{
return stat_time(statx_atimespec(get_stat(self)));
}
#birthtime ⇒ Time
Returns a new ::Time object containing the create time
of the object represented by self
at the time self was created;
see Snapshot:
filename = 't.tmp'
stat = File::Stat.new(filename) # Raises Errno::ENOENT: No such file or directory
File.write(filename, 'foo')
stat = File::Stat.new(filename)
stat.birthtime # => 2026-04-14 10:41:55.5146554 -0500
File.delete(filename)
stat.birthtime # => 2026-04-14 10:41:55.5146554 -0500
# File 'file.c', line 1215
static VALUE
rb_stat_birthtime(VALUE self)
{
return statx_birthtime(get_stat(self));
}
#blksize ⇒ Integer?
# File 'file.c', line 963
static VALUE
rb_stat_blksize(VALUE self)
{
#ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
return ULONG2NUM(get_stat(self)->ST_(blksize));
#else
return Qnil;
#endif
}
#blocks ⇒ Integer?
# File 'file.c', line 984
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
}
#ctime ⇒ Time
# File 'file.c', line 1188
static VALUE
rb_stat_ctime(VALUE self)
{
return stat_time(statx_ctimespec(get_stat(self)));
}
#dev ⇒ Integer
[ GitHub ]# File 'file.c', line 702
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
}
#dev_major ⇒ Integer
# File 'file.c', line 729
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
}
#dev_minor ⇒ Integer
# File 'file.c', line 752
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
}
#ftype ⇒ String
Returns the string type of the object at File.path, one of:
- 'file'.
- 'directory'.
- 'characterSpecial'.
- 'blockSpecial'.
- 'fifo'.
- 'link'.
- 'socket'.
Examples:
File.stat('README.md').ftype # => "file"
File.stat('lib').ftype # => "directory"
File.stat('/dev/null').ftype # => "characterSpecial"
File.stat('/dev/loop0').ftype # => "blockSpecial"
File.mkfifo('/tmp/pipe', 0666)
File.stat('/tmp/pipe').ftype # => "fifo"
# Follows symbolic link.
File.symlink('lib', 'lib_link')
File.stat('lib_link').ftype # => "directory"
# Does not follow symbolic link.
File.lstat('lib_link').ftype # => "link"
require 'socket'
UNIXServer.new('/tmp/socket')
File.stat('/tmp/socket').ftype # => "socket"
Returns 'unknown' if the type cannot be determined.
# File 'file.c', line 6660
static VALUE
rb_stat_ftype(VALUE obj)
{
return rb_file_ftype(get_stat(obj)->ST_(mode));
}
#gid ⇒ Integer
[ GitHub ]# File 'file.c', line 855
static VALUE
rb_stat_gid(VALUE self)
{
return GIDT2NUM(get_stat(self)->ST_(gid));
}
#initialize_copy(orig)
# File 'file.c', line 6608
static VALUE
rb_stat_init_copy(VALUE copy, VALUE orig)
{
if (!OBJ_INIT_COPY(copy, orig)) return copy;
struct rb_stat *orig_rb_st;
TypedData_Get_Struct(orig, struct rb_stat, &stat_data_type, orig_rb_st);
struct rb_stat *copy_rb_st;
TypedData_Get_Struct(copy, struct rb_stat, &stat_data_type, copy_rb_st);
*copy_rb_st = *orig_rb_st;
return copy;
}
#ino ⇒ Integer
[ GitHub ]# File 'file.c', line 774
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
}
#inspect ⇒ String
Produce a nicely formatted description of 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>"
# File 'file.c', line 1239
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;
}
#mode ⇒ Integer
# File 'file.c', line 802
static VALUE
rb_stat_mode(VALUE self)
{
return UINT2NUM(ST2UINT(get_stat(self)->ST_(mode)));
}
#mtime ⇒ Time
[ GitHub ]# File 'file.c', line 1168
static VALUE
rb_stat_mtime(VALUE self)
{
return stat_time(statx_mtimespec(get_stat(self)));
}
#nlink ⇒ Integer
# File 'file.c', line 820
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));
}
#rdev ⇒ Integer?
# File 'file.c', line 873
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
}
#rdev_major ⇒ Integer
# File 'file.c', line 902
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
}
#rdev_minor ⇒ Integer
# File 'file.c', line 925
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
}
#uid ⇒ Integer
[ GitHub ]# File 'file.c', line 839
static VALUE
rb_stat_uid(VALUE self)
{
return UIDT2NUM(get_stat(self)->ST_(uid));
}