Filesystem Modes

A filesystem entry has an integer mode that specifies:

The mode is most often seen as an octal-format integer:

On this page, we show a mode using format '%06o, which displays the mode as a 6-digit octal number:

'%06o' % File.stat('/etc/passwd').mode # => "100644"

Getting a Mode

You can use method File::Stat#mode to get the mode of a filesystem entry.

Each of these methods returns a File::Stat object for a given filesystem entry. The first three follow symbolic links; the others don’t:

Once you have the File::Stat object, you can fetch the mode for the entry:

'%06o' % File.stat('/etc').mode        # => "040755"
'%06o' % File.stat('/etc/passwd').mode # => "100644"

Setting a Mode

The mode for an entry is initialized when the entry is created:

filepath = '/tmp/t.txt'
File.write(filepath, 'foo')
'%06o' % File.stat(filepath).mode # => "100664"
File.delete(filepath)             # Clean up.
dirpath = '/tmp/bar'
Dir.mkdir(dirpath)
'%06o' % File.stat(dirpath).mode  # => "040775"
Dir.rmdir(dirpath)                # Clean up.

You can use one of these methods to change the permissions and special bits (but not the file type):

The actual effects of these methods is filesystem-dependent.

Permissions

A filesystem entry has permissions:

Executable Files

On Windows, a file is executable if its path has one of these file extensions: .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, a file is executable if it has the execute/search permission for the effective user and group id of the current process:

File.executable?('/bin/ruby')   # => true   # Executable file.
File.executable?('/etc')        # => true   # Searchable directory.
File.executable?('/etc/passwd') # => false  # Non-executable file.
File.executable?('nosuch')      # => false  # Non-existent.

Setting Permissions

For a method that actually creates a file in the underlying filesystem (as opposed to merely creating a File object), permissions may be specified; the permissions may also be changed:

filepath = '/tmp/t.tmp'
File.write(filepath, 'foo')
'%06o' % File.stat(filepath).mode # => "100664"
File.chmod(0o775, filepath)
'%06o' % File.stat(filepath).mode # => "100775"
File.delete(filepath)             # Clean up.

For a method that actually creates a directory in the underlying filesystem (as opposed to merely creating a Dir object), permissions may be specified; the permissions may also be changed:

dirpath = '/tmp/dir'
Dir.mkdir(dirpath)
'%06o' % File.stat(dirpath).mode # => "040775"
File.chmod(0o644, dirpath)
'%06o' % File.stat(dirpath).mode # => "040644"
Dir.rmdir(dirpath)               # Clean up.

On non-Posix operating systems, permissions may include only read-only or read-write, in which case, the remaining permission will resemble typical values. On Windows, for instance, the default permissions are 0644; The only change that can be made is to make the file read-only, which is reported as 0444.

Directory and File Permissions

Permissions for directories and files include read and write permissions.

The permissions in this table do not involve execute/search, and so apply similarly to a directory or a file.

Octal Permissions
0o000000 No permissions.
0o000400 Owner read-only.
0o000600 Owner read-write.
0o000644 Owner read-write; group/world read-only.
0o000664 Owner/group read-write; world read-only.
0o000666 Owner/group/world read-write.

File Permissions

Permissions for a file include execute permissions, in addition to the read and write permissions seen above.

The permissions in this table, applied to a file, specify execute permissions.

Octal Permissions
0o000700 Owner read-write-execute.
0o000750 Owner read-write-execute; group read-execute.
0o000755 Owner read-write-execute; group read-execute; world execute.
0o000775 Owner/group read-write-execute; world read-execute.
0o000777 Owner/group/world read-write-execute.

Directory Permissions

Permissions for a directory include search permissions, in addition to the read and write permissions seen above.

The permissions in this table, applied to a directory, specify search permissions.

Octal Permissions
0o000700 Owner read-write-search.
0o000750 Owner read-write-search; group read-search.
0o000755 Owner read-write-search; group read-search; world search.
0o000775 Owner/group read-write-search; world read-search.
0o000777 Owner/group/world read-write-search.

Special Bits

The fourth octal digit in a mode represents its special bits:

Octal Meaning
0o000000 None.
0o001000 Sticky.
0o002000 Setgid.
0o003000 Setgid + sticky.
0o004000 Setuid.
0o005000 Setuid + sticky.
0o006000 Setuid + setgid.
0o007000 Setuid + setgid + sticky.

Examples (note value in special-bits digit – fourth-from-left):

filepath = '/tmp/t.tmp'
File.write(filepath, 'foo')
'%06o' % File.stat(filepath).mode # => "100664"  # No special bits set.
File.chmod(0o1644, filepath)
'%06o' % File.stat(filepath).mode # => "101644"  # Sticky bit set.
File.chmod(0o2644, filepath)
'%06o' % File.stat(filepath).mode # => "102644"  # Setgid bit set.
File.chmod(0o4644, filepath)
'%06o' % File.stat(filepath).mode # => "104644"  # Setuid bit set.
File.chmod(0o7644, filepath)
'%06o' % File.stat(filepath).mode # => "107644"  # All special bits set.
File.delete(filepath)             # Clean up.

File Type

The fifth and sixth octal digits in a mode represent the file type:

Octal File Type
0o010000 Pipe.
0o020000 Character device.
0o040000 Directory.
0o060000 Block device.
0o100000 Regular file.
0o120000 Symbolic link.
0o140000 Socket.

Define a path for each file type:

pipe_path =              '/tmp/pipe'
character_special_path = '/dev/tty'
dir_path =               '/tmp'
block_special_path =     '/dev/loop0'
file_path =              '/etc/passwd'
link_path =              '/tmp/link'
socket_path =            '/tmp/socket'

For some of the paths, the entries exist already; these we have to create:

File.mkfifo(pipe_path, 0666)
File.symlink(file_path, link_path)
require 'socket'
UNIXServer.new(socket_path)

Show the modes (note the leftmost two digits):

'%06o' % File.stat(pipe_path).mode              # => "010664"
'%06o' % File.stat(character_special_path).mode # => "020666"
'%06o' % File.stat(dir_path).mode               # => "041777"
'%06o' % File.stat(block_special_path).mode     # => "060660"
'%06o' % File.stat(file_path).mode              # => "100644"
'%06o' % File.lstat(link_path).mode             # => "120777"  # lstat: Do not follow link.
'%06o' % File.stat(socket_path).mode            # => "140775"
File.delete(pipe_path, link_path, socket_path)  # Clean up.