Filesystem Modes

A filesystem entry has an integer mode that specifies:

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:

File.stat('README.md').mode.to_s(8) # => "100664"
File.stat('doc/').mode.to_s(8)      # => "40775"

On this page, we use a helper method to display a mode in a convenient form, showing the mode both as an octal integer and a string. If youโ€™re new to this page, it may be helpful to read about the helper method now.

Setting a Mode

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

filepath = '/tmp/t.txt'
File.write(filepath, 'foo')
mode(filepath) # => "100664 -rw-rw-r--"
dirpath = '/tmp/bar'
Dir.mkdir(dirpath)
mode(dirpath)  # => "040775 drwxrwxr-x"
File.unlink(filepath)
Dir.rmdir(dirpath)

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

Permissions

A filesystem entry has 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.new(filepath, 'w', 0755)
mode(filepath) # => "100755 -rwxr-xr-x"
File.chmod(0644, filepath)
mode(filepath) # => "100644 -rw-r--r--"

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, 0755)
mode(dirpath) # => "040755 drwxr-xr-x"
File.chmod(0644, dirpath)
mode(dirpath) # => "040644 drw-r--r--"

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 String Permissions
000 '---------' No permissions.
400 'r--------' Owner read-only.
600 'rw-------' Owner read-write.
644 'rw-r--r--' Owner read-write; group/world read-only.
664 'rw-rw-r--' Owner/group read-write; world read-only.
666 'rw-rw-rw-' 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 String Permissions
700 'rwx------' Owner read-write-execute.
750 'rwxr-x---' Owner read-write-execute; group read-execute.
755 'rwxr-xr-x' Owner read-write-execute; group read-execute; world execute.
775 'rwxrwxr-x' Owner/group read-write-execute; world read-execute.
777 'rwxrwxrwx' 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 String Permissions
700 'rwx------' Owner read-write-search.
750 'rwxr-x---' Owner read-write-search; group read-search.
755 'rwxr-xr-x' Owner read-write-search; group read-search; world search.
775 'rwxrwxr-x' Owner/group read-write-search; world read-search.
777 'rwxrwxrwx' Owner/group/world read-write-search.

Special Bits

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

Octal Meaning
0000 None.
1000 Sticky.
2000 Setgid.
3000 Setgid + sticky.
4000 Setuid.
5000 Setuid + sticky.
6000 Setuid + setgid.
7000 Setuid + setgid + sticky.

Examples:

File.write(filepath, '')
File.chmod(00644, filepath)
mode(filepath) # => "100644 -rw-r--r--"  # No special bits set.
File.chmod(01644, filepath)
mode(filepath) # => "101644 -rw-r--r-T"  # 'T' shows that sticky bit is set.
File.chmod(02644, filepath)
mode(filepath) # => "102644 -rw-r-Sr--"  # 'S' shows that setuid bit is set.
File.chmod(04644, filepath)
mode(filepath) # => "104644 -rwSr--r--"  # 'S' shows that setgid bit is set.
File.chmod(07644, filepath)
mode(filepath) # => "107644 -rwSr-Sr-T"  # All set.

In each case, if the execute bit is also set, lowercase letters 't' and 's' are displayed instead of uppercase 'T' and 'S':

File.chmod(00755, filepath)
mode(filepath) # => "100755 -rwxr-xr-x"
File.chmod(01755, filepath)
mode(filepath) # => "101755 -rwxr-xr-t"
File.chmod(02755, filepath)
mode(filepath) # => "102755 -rwxr-sr-x"
File.chmod(04755, filepath)
mode(filepath) # => "104755 -rwsr-xr-x"
File.chmod(07755, filepath)
mode(filepath) # => "107755 -rwsr-sr-t"

File Type

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

Octal Character File Type
010000 'p' Pipe.
020000 'c' Character device.
040000 'd' Directory.
060000 'b' Block device.
100000 '-' Regular file.
120000 'l' Symbolic link.
140000 's' Socket.

Examples:

File.mkfifo('/tmp/pipe', 0666)
mode('/tmp/pipe')   # => "010664 prw-rw-r--"  # 01; pipe.
mode('/dev/tty')    # => "020666 crw-rw-rw-"  # 02; character device.
mode('doc/')        # => "040775 drwxrwxr-x"  # 04; directory.
mode('/dev/loop0')  # => "060660 brw-rw----"  # 06; block device.
mode('README.md')   # => "100664 -rw-rw-r--"  # 10; regular file.
File.symlink('lib', '/tmp/link')
mode('/tmp/link')   # => "120777 lrwxrwxrwx"  # 12; symbolic link.
require 'socket'
UNIXServer.new('/tmp/socket')
mode('/tmp/socket') # => "140775 srwxrwxr-x"  # 14; socket.
File.unlink('/tmp/pipe', '/tmp/link' ,'/tmp/socket')

Helper Method

On this page, we use a helper method, mode, to show the mode information for a given path:

mode('README.md') # => "0100664 -rw-rw-r--"
mode('/etc')      # => "0040755 drwxr-xr-x"

The permissions are expressed both in:

The special bits are expressed in the fourth digit.

The file type is expressed the fifth and sixth digits.

For the code-curious:

# Return a string containing the mode (octal digits and character string)
# for the given path.
def mode(path)
  # Get mode digits from File.lstat.
  mode_digits = File.lstat(path).inspect.split(', ').select {|s| s.match('mode')}.first.split('=').last
  # Format to size.
  formatted_digits = "%06o" % mode_digits
  # Get mode characters from ls command.
  mode_characters = `ls -ld #{path}`.split(' ').first
  # Return both.
  "#{formatted_digits} #{mode_characters}"
end