module FileTest
FileTest implements file test operations similar to those used in File::Stat. It exists as a standalone module, and its methods are also insinuated into the File class. (Note that this is not done by inclusion: the interpreter cheats).
Public Instance Methods
(path | io file_name) → bool
Source
static VALUE
rb_file_blockdev_p(VALUE obj, VALUE fname)
{
#ifndef S_ISBLK
# ifdef S_IFBLK
# define S_ISBLK(m) (((m) & S_IFMT) == S_IFBLK)
# else
# define S_ISBLK(m) (0) /* anytime false */
# endif
#endif
#ifdef S_ISBLK
struct stat st;
if (rb_stat(fname, &st) < 0) return Qfalse;
if (S_ISBLK(st.st_mode)) return Qtrue;
#endif
return Qfalse;
}
Returns whether object (a path or IO object) represents a block device (i.e., a direct-access device):
File.blockdev?('/dev/nvme0n1') # => true File.blockdev?('/dev/loop0') # => true File.blockdev?('/dev/tty') # => false File.blockdev?('/dev/null') # => false File.blockdev?('nosuch') # => false File.blockdev?($stdin) # => false
The returned value is filesystem-dependent; on Windows, always false.
(path | io file_name) → bool
Source
static VALUE
rb_file_chardev_p(VALUE obj, VALUE fname)
{
#ifndef S_ISCHR
# define S_ISCHR(m) (((m) & S_IFMT) == S_IFCHR)
#endif
struct stat st;
if (rb_stat(fname, &st) < 0) return Qfalse;
if (S_ISCHR(st.st_mode)) return Qtrue;
return Qfalse;
}
Returns whether object (a path or IO object) represents a character device (i.e., a sequential-access device):
File.chardev?('/dev/tty') # => true File.chardev?('/dev/null') # => true File.chardev?($stdin) # => true File.chardev?('/dev/nvme0n1') # => false File.chardev?('/dev/loop0') # => false File.chardev?('nosuch') # => false
The returned value is filesystem-dependent; on Windows, always false.
(path | io file_name) → bool
Source
VALUE
rb_file_directory_p(VALUE obj, VALUE fname)
{
#ifndef S_ISDIR
# define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
#endif
struct stat st;
if (rb_stat(fname, &st) < 0) return Qfalse;
if (S_ISDIR(st.st_mode)) return Qtrue;
return Qfalse;
}
Returns whether the given object represents a directory; object may be a string path or an IO object:
File.directory?('/etc') # => true File.directory?('lib') # => true File.directory?('README.md') # => false File.directory?('nosuch') # => false File.directory?($stdin) # => false
Follows symbolic links:
dirpath = 'doc/dirname' File.symlink('.', dirpath) File.directory?(dirpath) # => true File.unlink(dirpath) filepath = 't.tmp' File.symlink('README.md', filepath) File.directory?(filepath) # => false File.unlink(filepath)
(path | io file_name) → bool
Returns whether the given object exists and has size zero.
The given object may be the path to a file:
filepath = '/tmp/t.tmp' File.write(filepath, 'foo') # File has non-zero size. File.zero?(filepath) # => false File.truncate(filepath, 0) # File has zero size. File.zero?(filepath) # => true File.delete(filepath) # Clean up.
The given object may be the path to a directory:
dirpath = '/tmp/foo' Dir.mkdir(dirpath) Dir.new(dirpath).children.size # => 0 # Size is filesystem-dependent; may or may not be zero. File.size(dirpath) # => 4096 File.zero?(dirpath) # => false filepath = '/tmp/foo/t.tmp' # => "/tmp/foo/t.tmp" File.write(filepath, 'foo') # Add a child. Dir.new(dirpath).children.size # => 1 File.size(dirpath) # => 4096 File.zero?(dirpath) # => false FileUtils.rm_rf(dirpath) # Clean up.
The given object may be an IO object:
File.zero?($stdin) # => true
The given object may be none of the above:
File.zero?('nosuch') # => false
(path file_name) → bool
Source
static VALUE
rb_file_executable_p(VALUE obj, VALUE fname)
{
return RBOOL(rb_eaccess(fname, X_OK) >= 0);
}
Returns whether the filesystem entry at the given string path exists and is executable.
On Windows, the entry is executable if its path has file extension .bat, .cmd, .com, or .exe:
File.executable?('win32/rtname.cmd') # => true File.executable?('win32/rtname') # => false File.executable?('win32/nosuch.cmd') # => 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.
File.executable?('/bin/bash') # => true File.executable?('.') # => true File.executable?('/etc/passwd') # => false File.executable?('nosuch') # => false
Note that some filesystem settings may cause this method to return true even though the entry is not executable by the effective user/group.
(path file_name) → bool
Source
static VALUE
rb_file_executable_real_p(VALUE obj, VALUE fname)
{
return RBOOL(rb_access(fname, X_OK) >= 0);
}
Returns true if the named file is executable by the real user and group id of this process. See access(3).
Windows does not support execute permissions separately from read permissions. On Windows, a file is only considered executable if it ends in .bat, .cmd, .com, or .exe.
Note that some OS-level security features may cause this to return true even though the file is not executable by the real user/group.
(path | io file_name) → bool
Source
static VALUE
rb_file_exist_p(VALUE obj, VALUE fname)
{
struct stat st;
if (rb_stat(fname, &st) < 0) return Qfalse;
return Qtrue;
}
Return whether the specified object, a string path or IO object, exists:
# String paths. File.exist?('README.md') # => true File.exist?('.') # => true filepath = 't.tmp' File.exist?(filepath) # => false File.write(filepath, 'foo') File.exist?(filepath) # => true # File (IO object). file = File.new(filepath) File.exist?(file) # => true file.close # Clean up. File.unlink(filepath) # Clean up.
Follows symbolic links:
# Symbolic links. File.symlink('README.md', 'README.link') File.symlink('nosuch', 'BROKEN.link') File.exist?('README.link') # => true File.exist?('BROKEN.link') # => false File.unlink('README.link') # Clean up. File.unlink('BROKEN.link') # Clean up.
(path | io file) → bool
Source
static VALUE
rb_file_file_p(VALUE obj, VALUE fname)
{
struct stat st;
if (rb_stat(fname, &st) < 0) return Qfalse;
return RBOOL(S_ISREG(st.st_mode));
}
Returns whether the given object, a string path or IO object, represents a filesystem entry that exists and is a regular file; see File.ftype:
# Paths. File.file?('README.md') # => true File.file?('doc/') # => false File.file?('nosuch') # => false # IO objects. file = File.new('README.md') File.file?(file) # => true dir = Dir.new('doc/') File.file?(dir) # => false # Clean up. file.close dir.close
(path | io file_name) → bool
Source
static VALUE
rb_file_grpowned_p(VALUE obj, VALUE fname)
{
#ifndef _WIN32
struct stat st;
if (rb_stat(fname, &st) < 0) return Qfalse;
if (rb_group_member(st.st_gid)) return Qtrue;
#endif
return Qfalse;
}
Returns whether the filesystem entry for the given object exists, and the effective group id of the calling process is the owner of the entry.
The given object may be the string path to a file or directory entry:
File.grpowned?('lib') # => true File.grpowned?('README.md') # => true File.grpowned?('/etc/passwd') # => false File.grpowned?('nosuch') # => false
Or an open IO stream:
File.open('README.md', 'r') {|file| File.grpowned?(file) } # => true File.open('/etc/passwd', 'r') {|file| File.grpowned?(file) } # => false
Returns false on Windows.
(path | io file_1, path | io file_2) → bool
Source
static VALUE
rb_file_identical_p(VALUE obj, VALUE fname1, VALUE fname2)
{
#ifndef _WIN32
struct stat st1, st2;
if (rb_stat(fname1, &st1) < 0) return Qfalse;
if (rb_stat(fname2, &st2) < 0) return Qfalse;
if (st1.st_dev != st2.st_dev) return Qfalse;
if (st1.st_ino != st2.st_ino) return Qfalse;
return Qtrue;
#else
extern VALUE rb_w32_file_identical_p(VALUE, VALUE);
return rb_w32_file_identical_p(fname1, fname2);
#endif
}
Returns whether the given objects represent filesystem entries that are identical; each object may be a string path or an IO object:
# Paths. File.identical?('README.md', 'README.md') # => true # Same path. File.identical?('README.md', './README.md') # => true # Same entry. File.identical?('.', '.') # => true # Directory. File.identical?('README.md', 'LEGAL') # => false File.identical?('README.md', 'nosuch') # => false # Non-existent entry. # Links and File object. File.link('README.md', 'link') # Symbolic link. File.symlink('README.md', 'symlink') # Hard link. file = File.open('README.md', 'r') # File object. File.identical?('README.md', 'link') # => true File.identical?('README.md', 'symlink') # => true File.identical?('README.md', file) # => true # Clean up. File.unlink('link') File.unlink('symlink') file.close
(path | io file_name) → bool
Source
static VALUE
rb_file_owned_p(VALUE obj, VALUE fname)
{
struct stat st;
if (rb_stat(fname, &st) < 0) return Qfalse;
return RBOOL(st.st_uid == geteuid());
}
Returns whether the given object represents a filesystem entry or IO object that exists and is owned by the user of the current process:
filepath = 'doc/t.tmp' File.write(filepath, 'foo') File.owned?(filepath) # => true File.delete(filepath) # Clean up. dirpath = 'doc/tmp' Dir.mkdir(dirpath) File.owned?(dirpath) # => true Dir.rmdir(dirpath) # Clean up. File.owned?($stdin) # => true File.owned?('/etc') # => false
(path | io file_name) → bool
Source
static VALUE
rb_file_pipe_p(VALUE obj, VALUE fname)
{
#ifdef S_IFIFO
# ifndef S_ISFIFO
# define S_ISFIFO(m) (((m) & S_IFMT) == S_IFIFO)
# endif
struct stat st;
if (rb_stat(fname, &st) < 0) return Qfalse;
if (S_ISFIFO(st.st_mode)) return Qtrue;
#endif
return Qfalse;
}
Returns whether the entry at the given path is a pipe:
File.pipe?('doc/syntax/') # => false # Directory. File.pipe?('doc/maintainers.md') # => false # Regular file. File.pipe?('nosuch') # => false # Non-existent. path = '/tmp/foo' File.mkfifo(path) File.pipe?(path) # => true File.delete(path) # Clean up.
(path file_name) → bool
Source
static VALUE
rb_file_readable_p(VALUE obj, VALUE fname)
{
return RBOOL(rb_eaccess(fname, R_OK) >= 0);
}
Returns whether the entry at the given path exists and is readable by the owner and group of the current process; see Permissions:
path = '/tmp/secret.txt' File.write(path, 'foo') File.readable?(path) # => true File.chmod(0o000, path) File.readable?(path) # => false File.delete(path) # Clean up. File.readable?('nosuch') # => false
(path file_name) → bool
Source
static VALUE
rb_file_readable_real_p(VALUE obj, VALUE fname)
{
return RBOOL(rb_access(fname, R_OK) >= 0);
}
Like File.readable?, but checks against the real user and group ids instead of the effective ids.
(path | io file_name) → bool
Source
static VALUE
rb_file_sgid_p(VALUE obj, VALUE fname)
{
#ifdef S_ISGID
return check3rdbyte(fname, S_ISGID);
#else
return Qfalse;
#endif
}
Returns whether the setgid bit is set in the special bits for the given object, which may be a path or an IO object:
path = '/tmp/t.tmp' File.write(path, 'foo') mode = File.stat(path).mode.to_s(8) # => "100664" File.setgid?(path) # => false File.chmod(0o2644, path) # Set the bit. mode = File.stat(path).mode.to_s(8) # => "102644" File.setgid?(path) # => true File.delete(path) # Clean up. File.setgid?($stdin) # => false
On Windows, the bit is never set; the method always returns false.
(path | io file_name) → bool
Source
static VALUE
rb_file_suid_p(VALUE obj, VALUE fname)
{
#ifdef S_ISUID
return check3rdbyte(fname, S_ISUID);
#else
return Qfalse;
#endif
}
Returns whether the setuid bit is set in the special bits for the given object, which may be a path or an IO object:
path = '/tmp/t.tmp' File.write(path, 'foo') mode = File.stat(path).mode.to_s(8) # => "100664" File.setuid?(path) # => false File.chmod(0o4644, path) # Set the bit. mode = File.stat(path).mode.to_s(8) # => "104644" File.setuid?(path) # => true File.delete(path) # Clean up. File.setuid?($stdin) # => false
On Windows, the bit is never set; the method always returns false.
(path | io file_name) → Integer
Source
static VALUE
rb_file_s_size(VALUE klass, VALUE fname)
{
struct stat st;
if (rb_stat(fname, &st) < 0) {
int e = errno;
FilePathValue(fname);
rb_syserr_fail_path(e, fname);
}
return OFFT2NUM(st.st_size);
}
Returns the size in bytes of the given object, which may be a path or an IO object:
File.size('doc/maintainers.md') # => 14900 # Regular file. File.size('doc/syntax/') # => 4096 # Directory. File.size($stdin) # => 0 # IO object.
(path | io file_name) → Integer?
Source
static VALUE
rb_file_size_p(VALUE obj, VALUE fname)
{
struct stat st;
if (rb_stat(fname, &st) < 0) return Qnil;
if (st.st_size == 0) return Qnil;
return OFFT2NUM(st.st_size);
}
Returns the size in bytes of the given object if the entry exists and has non-zero size, nil otherwise; the object may be a path or an IO object:
# Regular file. path = '/tmp/t.tmp' File.write(path, 'foo') File.size?(path) # => 3 # Non-zero size. File.write(path, '') File.size?(path) # => nil # Zero size. File.delete(path) # Clean up. File.size?(path) # => nil # Non-existent. # Directory. path = '/tmp/foo/' Dir.mkdir(path) File.size?(path) # => 4096 # Non-zero size. Dir.rmdir(path) # Clean up. File.size?(path) # => nil # Non-existent.
(path | io file_name) → bool
Source
static VALUE
rb_file_socket_p(VALUE obj, VALUE fname)
{
#ifndef S_ISSOCK
# ifdef _S_ISSOCK
# define S_ISSOCK(m) _S_ISSOCK(m)
# else
# ifdef _S_IFSOCK
# define S_ISSOCK(m) (((m) & S_IFMT) == _S_IFSOCK)
# else
# ifdef S_IFSOCK
# define S_ISSOCK(m) (((m) & S_IFMT) == S_IFSOCK)
# endif
# endif
# endif
#endif
#ifdef S_ISSOCK
struct stat st;
if (rb_stat(fname, &st) < 0) return Qfalse;
if (S_ISSOCK(st.st_mode)) return Qtrue;
#endif
return Qfalse;
}
Returns whether the given object represents a socket; the object may be a path or an IO object:
require 'socket' sock_path = '/tmp/socket' server = UNIXServer.new(sock_path) File.socket?(sock_path) # => true File.delete(sock_path) # Clean up. file_path = '/etc/passwd' File.file?(file_path) # => true File.socket?(file_path) # => false File.socket?($stdin) # => false File.socket?('nosuch') # => false
(path | io file_name) → bool
Source
static VALUE
rb_file_sticky_p(VALUE obj, VALUE fname)
{
#ifdef S_ISVTX
return check3rdbyte(fname, S_ISVTX);
#else
return Qfalse;
#endif
}
Returns whether the sticky bit is set in the special bits for the given object, which may be a path or an IO object:
filepath = '/tmp/t.tmp' File.write(filepath, 'foo') mode = File.stat(filepath).mode.to_s(8) # => "100664" File.sticky?(filepath) # => false File.chmod(01644, filepath) # Set sticky bit. mode = File.stat(filepath).mode.to_s(8) # => "101644" File.sticky?(filepath) # => true File.delete(filepath) # Clean up. File.sticky?($stdin) # => false File.sticky?('nosuch') # => false
Returns false on Windows.
(path file_name) → bool
Source
static VALUE
rb_file_symlink_p(VALUE obj, VALUE fname)
{
#ifndef S_ISLNK
# ifdef _S_ISLNK
# define S_ISLNK(m) _S_ISLNK(m)
# else
# ifdef _S_IFLNK
# define S_ISLNK(m) (((m) & S_IFMT) == _S_IFLNK)
# else
# ifdef S_IFLNK
# define S_ISLNK(m) (((m) & S_IFMT) == S_IFLNK)
# endif
# endif
# endif
#endif
#ifdef S_ISLNK
struct stat st;
FilePathValue(fname);
fname = rb_str_encode_ospath(fname);
if (lstat_without_gvl(StringValueCStr(fname), &st) < 0) return Qfalse;
if (S_ISLNK(st.st_mode)) return Qtrue;
#endif
return Qfalse;
}
Returns whether the entry at path is a symbolic link:
filepath = '/etc/passwd' linkpath = '/tmp/foo' File.symlink(filepath, linkpath) File.symlink?(filepath) # => false File.symlink?(linkpath) # => true File.symlink?('.') # => false File.delete(linkpath) # Clean up.
(path | io file_name) → Integer?
Source
static VALUE
rb_file_world_readable_p(VALUE obj, VALUE fname)
{
#ifdef S_IROTH
struct stat st;
if (rb_stat(fname, &st) < 0) return Qnil;
if ((st.st_mode & (S_IROTH)) == S_IROTH) {
return UINT2NUM(st.st_mode & (S_IRUGO|S_IWUGO|S_IXUGO));
}
#endif
return Qnil;
}
If the the given object exists and is readable by others, returns the integer permissions for the entry; otherwise, returns nil:
filepath = '/tmp/t.tmp' File.world_readable?(filepath) # => nil # Non-existent. File.write(filepath, 'foo') # Create file. File.world_readable?(filepath).to_s(8) # => "664" # World-readable. File.chmod(0o000, filepath) # Change to unreadable. File.world_readable?(filepath) # => nil # Not world-readable. File.delete(filepath) # Clean up. File.world_readable?('.').to_s(8) # => "775" # Directory. File.world_readable?($stdin) # => nil # IO object.
(path | io file_name) → Integer?
Source
static VALUE
rb_file_world_writable_p(VALUE obj, VALUE fname)
{
#ifdef S_IWOTH
struct stat st;
if (rb_stat(fname, &st) < 0) return Qnil;
if ((st.st_mode & (S_IWOTH)) == S_IWOTH) {
return UINT2NUM(st.st_mode & (S_IRUGO|S_IWUGO|S_IXUGO));
}
#endif
return Qnil;
}
If the given object exists and is writable by others, returns the integer permissions for the entry; otherwise, returns nil:
filepath = '/tmp/t.tmp' File.world_writable?(filepath) # => nil # Non-existent. File.write(filepath, 'foo') # Create file. File.world_writable?(filepath) # => nil # Not world-writable. File.chmod(0o777, filepath) # Make world-writable. File.world_writable?(filepath).to_s(8) # => "777" # World-writable. File.delete(filepath) # Clean up. File.world_writable?('/tmp').to_s(8) # => "777" # Directory. File.world_writable?($stdin) # => nil # IO object.
(path file_name) → bool
Source
static VALUE
rb_file_writable_p(VALUE obj, VALUE fname)
{
return RBOOL(rb_eaccess(fname, W_OK) >= 0);
}
Returns whether given object exists and is writable by the owner and group in the current process:
filepath = '/tmp/secret.txt' File.writable?(filepath) # => false # Non-existent. File.write(filepath, 'foo') # Create file. File.writable?(filepath) # => true # Writable. File.chmod(0o000, filepath) # Make non-writable. File.writable?(filepath) # => false # Not writable. File.delete(filepath) # Clean up. File.writable?('/etc') # => false # Directory. File.writable?($stdin) # => false # IO object.
Note that filesystem security features may cause this method to return true even when the file is not writable by the owner and group.
(path file_name) → bool
Source
static VALUE
rb_file_writable_real_p(VALUE obj, VALUE fname)
{
return RBOOL(rb_access(fname, W_OK) >= 0);
}
Like File.writable?, but checks against the real owner and group instead of the effective owner and group.
Note that filesystem security features may cause this method to return true even when the object is not writable by the real owner and group.
(path | io file_name) → bool
Source
static VALUE
rb_file_zero_p(VALUE obj, VALUE fname)
{
struct stat st;
if (rb_stat(fname, &st) < 0) return Qfalse;
return RBOOL(st.st_size == 0);
}
Returns whether the given object exists and has size zero.
The given object may be the path to a file:
filepath = '/tmp/t.tmp' File.write(filepath, 'foo') # File has non-zero size. File.zero?(filepath) # => false File.truncate(filepath, 0) # File has zero size. File.zero?(filepath) # => true File.delete(filepath) # Clean up.
The given object may be the path to a directory:
dirpath = '/tmp/foo' Dir.mkdir(dirpath) Dir.new(dirpath).children.size # => 0 # Size is filesystem-dependent; may or may not be zero. File.size(dirpath) # => 4096 File.zero?(dirpath) # => false filepath = '/tmp/foo/t.tmp' # => "/tmp/foo/t.tmp" File.write(filepath, 'foo') # Add a child. Dir.new(dirpath).children.size # => 1 File.size(dirpath) # => 4096 File.zero?(dirpath) # => false FileUtils.rm_rf(dirpath) # Clean up.
The given object may be an IO object:
File.zero?($stdin) # => true
The given object may be none of the above:
File.zero?('nosuch') # => false