# <!-- rdoc-file=lib/fileutils.rb -->
# Namespace for file utility methods for copying, moving, removing, etc.
#
# ## What's Here
#
# First, what’s elsewhere. Module FileUtils:
#
# *   Inherits from [class Object](rdoc-ref:Object).
# *   Supplements [class File](rdoc-ref:File) (but is not included or extended
#     there).
#
# Here, module FileUtils provides methods that are useful for:
#
# *   [Creating](rdoc-ref:FileUtils@Creating).
# *   [Deleting](rdoc-ref:FileUtils@Deleting).
# *   [Querying](rdoc-ref:FileUtils@Querying).
# *   [Setting](rdoc-ref:FileUtils@Setting).
# *   [Comparing](rdoc-ref:FileUtils@Comparing).
# *   [Copying](rdoc-ref:FileUtils@Copying).
# *   [Moving](rdoc-ref:FileUtils@Moving).
# *   [Options](rdoc-ref:FileUtils@Options).
#
# ### Creating
#
# *   ::mkdir: Creates directories.
# *   ::mkdir_p, ::makedirs, ::mkpath: Creates directories, also creating
#     ancestor directories as needed.
# *   ::link_entry: Creates a hard link.
# *   ::ln, ::link: Creates hard links.
# *   ::ln_s, ::symlink: Creates symbolic links.
# *   ::ln_sf: Creates symbolic links, overwriting if necessary.
# *   ::ln_sr: Creates symbolic links relative to targets
#
# ### Deleting
#
# *   ::remove_dir: Removes a directory and its descendants.
# *   ::remove_entry: Removes an entry, including its descendants if it is a
#     directory.
# *   ::remove_entry_secure: Like ::remove_entry, but removes securely.
# *   ::remove_file: Removes a file entry.
# *   ::rm, ::remove: Removes entries.
# *   ::rm_f, ::safe_unlink: Like ::rm, but removes forcibly.
# *   ::rm_r: Removes entries and their descendants.
# *   ::rm_rf, ::rmtree: Like ::rm_r, but removes forcibly.
# *   ::rmdir: Removes directories.
#
# ### Querying
#
# *   ::pwd, ::getwd: Returns the path to the working directory.
# *   ::uptodate?: Returns whether a given entry is newer than given other
#     entries.
#
# ### Setting
#
# *   ::cd, ::chdir: Sets the working directory.
# *   ::chmod: Sets permissions for an entry.
# *   ::chmod_R: Sets permissions for an entry and its descendants.
# *   ::chown: Sets the owner and group for entries.
# *   ::chown_R: Sets the owner and group for entries and their descendants.
# *   ::touch: Sets modification and access times for entries, creating if
#     necessary.
#
# ### Comparing
#
# *   ::compare_file, ::cmp, ::identical?: Returns whether two entries are
#     identical.
# *   ::compare_stream: Returns whether two streams are identical.
#
# ### Copying
#
# *   ::copy_entry: Recursively copies an entry.
# *   ::copy_file: Copies an entry.
# *   ::copy_stream: Copies a stream.
# *   ::cp, ::copy: Copies files.
# *   ::cp_lr: Recursively creates hard links.
# *   ::cp_r: Recursively copies files, retaining mode, owner, and group.
# *   ::install: Recursively copies files, optionally setting mode, owner, and
#     group.
#
# ### Moving
#
# *   ::mv, ::move: Moves entries.
#
# ### Options
#
# *   ::collect_method: Returns the names of methods that accept a given option.
# *   ::commands: Returns the names of methods that accept options.
# *   ::have_option?: Returns whether a given method accepts a given option.
# *   ::options: Returns all option names.
# *   ::options_of: Returns the names of the options for a given method.
#
# ## Path Arguments
#
# Some methods in FileUtils accept *path* arguments, which are interpreted as
# paths to filesystem entries:
#
# *   If the argument is a string, that value is the path.
# *   If the argument has method `:to_path`, it is converted via that method.
# *   If the argument has method `:to_str`, it is converted via that method.
#
# ## About the Examples
#
# Some examples here involve trees of file entries. For these, we sometimes
# display trees using the [tree command-line
# utility](https://en.wikipedia.org/wiki/Tree_(command)), which is a recursive
# directory-listing utility that produces a depth-indented listing of files and
# directories.
#
# We use a helper method to launch the command and control the format:
#
#     def tree(dirpath = '.')
#       command = "tree --noreport --charset=ascii #{dirpath}"
#       system(command)
#     end
#
# To illustrate:
#
#     tree('src0')
#     # => src0
#     #    |-- sub0
#     #    |   |-- src0.txt
#     #    |   `-- src1.txt
#     #    `-- sub1
#     #        |-- src2.txt
#     #        `-- src3.txt
#
# ## Avoiding the TOCTTOU Vulnerability
#
# For certain methods that recursively remove entries, there is a potential
# vulnerability called the [Time-of-check to
# time-of-use](https://en.wikipedia.org/wiki/Time-of-check_to_time-of-use), or
# TOCTTOU, vulnerability that can exist when:
#
# *   An ancestor directory of the entry at the target path is world writable;
#     such directories include `/tmp`.
# *   The directory tree at the target path includes:
#
#     *   A world-writable descendant directory.
#     *   A symbolic link.
#
# To avoid that vulnerability, you can use this method to remove entries:
#
# *   FileUtils.remove_entry_secure: removes recursively if the target path
#     points to a directory.
#
# Also available are these methods, each of which calls
# FileUtils.remove_entry_secure:
#
# *   FileUtils.rm_r with keyword argument `secure: true`.
# *   FileUtils.rm_rf with keyword argument `secure: true`.
#
# Finally, this method for moving entries calls FileUtils.remove_entry_secure if
# the source and destination are on different file systems (which means that the
# "move" is really a copy and remove):
#
# *   FileUtils.mv with keyword argument `secure: true`.
#
# Method FileUtils.remove_entry_secure removes securely by applying a special
# pre-process:
#
# *   If the target path points to a directory, this method uses methods
#     [File#chown](rdoc-ref:File#chown) and [File#chmod](rdoc-ref:File#chmod) in
#     removing directories.
# *   The owner of the target directory should be either the current process or
#     the super user (root).
#
# WARNING: You must ensure that **ALL** parent directories cannot be moved by
# other untrusted users.  For example, parent directories should not be owned by
# untrusted users, and should not be world writable except when the sticky bit
# is set.
#
# For details of this security vulnerability, see Perl cases:
#
# *   [CVE-2005-0448](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CAN-2005-04
#     48).
# *   [CVE-2004-0452](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CAN-2004-04
#     52).
#
module FileUtils
  # <!-- rdoc-file=lib/fileutils.rb -->
  # The version number.
  #
  VERSION: String

  type mode = Integer | String

  type path = string | _ToPath

  type pathlist = path | Array[path]

  # <!--
  #   rdoc-file=lib/fileutils.rb
  #   - cd(dir, verbose: nil) { |dir| ... }
  # -->
  # Changes the working directory to the given `dir`, which should be
  # [interpretable as a path](rdoc-ref:FileUtils@Path+Arguments):
  #
  # With no block given, changes the current directory to the directory at `dir`;
  # returns zero:
  #
  #     FileUtils.pwd # => "/rdoc/fileutils"
  #     FileUtils.cd('..')
  #     FileUtils.pwd # => "/rdoc"
  #     FileUtils.cd('fileutils')
  #
  # With a block given, changes the current directory to the directory at `dir`,
  # calls the block with argument `dir`, and restores the original current
  # directory; returns the block's value:
  #
  #     FileUtils.pwd                                     # => "/rdoc/fileutils"
  #     FileUtils.cd('..') { |arg| [arg, FileUtils.pwd] } # => ["..", "/rdoc"]
  #     FileUtils.pwd                                     # => "/rdoc/fileutils"
  #
  # Keyword arguments:
  #
  # *   `verbose: true` - prints an equivalent command:
  #
  #         FileUtils.cd('..')
  #         FileUtils.cd('fileutils')
  #
  #     Output:
  #
  #         cd ..
  #         cd fileutils
  #
  # Related: FileUtils.pwd.
  #
  def self?.cd: (path dir, ?verbose: boolish) -> void
              | [X] (path dir, ?verbose: boolish) { (String) -> X } -> X

  # <!--
  #   rdoc-file=lib/fileutils.rb
  #   - chdir(dir, verbose: nil)
  # -->
  #
  alias self.chdir self.cd

  # <!--
  #   rdoc-file=lib/fileutils.rb
  #   - chdir(dir, verbose: nil)
  # -->
  #
  alias chdir cd

  # <!--
  #   rdoc-file=lib/fileutils.rb
  #   - chmod(mode, list, noop: nil, verbose: nil)
  # -->
  # Changes permissions on the entries at the paths given in `list` (a single path
  # or an array of paths) to the permissions given by `mode`; returns `list` if it
  # is an array, `[list]` otherwise:
  #
  # *   Modifies each entry that is a regular file using
  #     [File.chmod](rdoc-ref:File.chmod).
  # *   Modifies each entry that is a symbolic link using
  #     [File.lchmod](rdoc-ref:File.lchmod).
  #
  # Argument `list` or its elements should be [interpretable as
  # paths](rdoc-ref:FileUtils@Path+Arguments).
  #
  # Argument `mode` may be either an integer or a string:
  #
  # *   Integer `mode`: represents the permission bits to be set:
  #
  #         FileUtils.chmod(0755, 'src0.txt')
  #         FileUtils.chmod(0644, ['src0.txt', 'src0.dat'])
  #
  # *   String `mode`: represents the permissions to be set:
  #
  #     The string is of the form `[targets][[operator][perms[,perms]]`, where:
  #
  #     *   `targets` may be any combination of these letters:
  #
  #         *   `'u'`: permissions apply to the file's owner.
  #         *   `'g'`: permissions apply to users in the file's group.
  #         *   `'o'`: permissions apply to other users not in the file's group.
  #         *   `'a'` (the default): permissions apply to all users.
  #
  #     *   `operator` may be one of these letters:
  #
  #         *   `'+'`: adds permissions.
  #         *   `'-'`: removes permissions.
  #         *   `'='`: sets (replaces) permissions.
  #
  #     *   `perms` (may be repeated, with separating commas) may be any
  #         combination of these letters:
  #
  #         *   `'r'`: Read.
  #         *   `'w'`: Write.
  #         *   `'x'`: Execute (search, for a directory).
  #         *   `'X'`: Search (for a directories only; must be used with `'+'`)
  #         *   `'s'`: Uid or gid.
  #         *   `'t'`: Sticky bit.
  #
  #     Examples:
  #
  #         FileUtils.chmod('u=wrx,go=rx', 'src1.txt')
  #         FileUtils.chmod('u=wrx,go=rx', '/usr/bin/ruby')
  #
  # Keyword arguments:
  #
  # *   `noop: true` - does not change permissions; returns `nil`.
  # *   `verbose: true` - prints an equivalent command:
  #
  #         FileUtils.chmod(0755, 'src0.txt', noop: true, verbose: true)
  #         FileUtils.chmod(0644, ['src0.txt', 'src0.dat'], noop: true, verbose: true)
  #         FileUtils.chmod('u=wrx,go=rx', 'src1.txt', noop: true, verbose: true)
  #         FileUtils.chmod('u=wrx,go=rx', '/usr/bin/ruby', noop: true, verbose: true)
  #
  #     Output:
  #
  #         chmod 755 src0.txt
  #         chmod 644 src0.txt src0.dat
  #         chmod u=wrx,go=rx src1.txt
  #         chmod u=wrx,go=rx /usr/bin/ruby
  #
  # Related: FileUtils.chmod_R.
  #
  def self?.chmod: (mode mode, pathlist list, ?noop: boolish, ?verbose: boolish) -> void

  # <!--
  #   rdoc-file=lib/fileutils.rb
  #   - chmod_R(mode, list, noop: nil, verbose: nil, force: nil)
  # -->
  # Like FileUtils.chmod, but changes permissions recursively.
  #
  def self?.chmod_R: (mode mode, pathlist list, ?noop: boolish, ?verbose: boolish, ?force: boolish) -> void

  # <!--
  #   rdoc-file=lib/fileutils.rb
  #   - chown(user, group, list, noop: nil, verbose: nil)
  # -->
  # Changes the owner and group on the entries at the paths given in `list` (a
  # single path or an array of paths) to the given `user` and `group`; returns
  # `list` if it is an array, `[list]` otherwise:
  #
  # *   Modifies each entry that is a regular file using
  #     [File.chown](rdoc-ref:File.chown).
  # *   Modifies each entry that is a symbolic link using
  #     [File.lchown](rdoc-ref:File.lchown).
  #
  # Argument `list` or its elements should be [interpretable as
  # paths](rdoc-ref:FileUtils@Path+Arguments).
  #
  # User and group:
  #
  # *   Argument `user` may be a user name or a user id; if `nil` or `-1`, the
  #     user is not changed.
  # *   Argument `group` may be a group name or a group id; if `nil` or `-1`, the
  #     group is not changed.
  # *   The user must be a member of the group.
  #
  # Examples:
  #
  #     # One path.
  #     # User and group as string names.
  #     File.stat('src0.txt').uid # => 1004
  #     File.stat('src0.txt').gid # => 1004
  #     FileUtils.chown('user2', 'group1', 'src0.txt')
  #     File.stat('src0.txt').uid # => 1006
  #     File.stat('src0.txt').gid # => 1005
  #
  #     # User and group as uid and gid.
  #     FileUtils.chown(1004, 1004, 'src0.txt')
  #     File.stat('src0.txt').uid # => 1004
  #     File.stat('src0.txt').gid # => 1004
  #
  #     # Array of paths.
  #     FileUtils.chown(1006, 1005, ['src0.txt', 'src0.dat'])
  #
  #     # Directory (not recursive).
  #     FileUtils.chown('user2', 'group1', '.')
  #
  # Keyword arguments:
  #
  # *   `noop: true` - does not change permissions; returns `nil`.
  # *   `verbose: true` - prints an equivalent command:
  #
  #         FileUtils.chown('user2', 'group1', 'src0.txt', noop: true, verbose: true)
  #         FileUtils.chown(1004, 1004, 'src0.txt', noop: true, verbose: true)
  #         FileUtils.chown(1006, 1005, ['src0.txt', 'src0.dat'], noop: true, verbose: true)
  #         FileUtils.chown('user2', 'group1', path, noop: true, verbose: true)
  #         FileUtils.chown('user2', 'group1', '.', noop: true, verbose: true)
  #
  #     Output:
  #
  #         chown user2:group1 src0.txt
  #         chown 1004:1004 src0.txt
  #         chown 1006:1005 src0.txt src0.dat
  #         chown user2:group1 src0.txt
  #         chown user2:group1 .
  #
  # Related: FileUtils.chown_R.
  #
  def self?.chown: (String? user, String? group, pathlist list, ?noop: boolish, ?verbose: boolish) -> void

  # <!--
  #   rdoc-file=lib/fileutils.rb
  #   - chown_R(user, group, list, noop: nil, verbose: nil, force: nil)
  # -->
  # Like FileUtils.chown, but changes owner and group recursively.
  #
  def self?.chown_R: (String? user, String? group, pathlist list, ?noop: boolish, ?verbose: boolish, ?force: boolish) -> void

  # <!--
  #   rdoc-file=lib/fileutils.rb
  #   - collect_method(opt)
  # -->
  # Returns an array of the string method names of the methods that accept the
  # given keyword option `opt`; the argument must be a symbol:
  #
  #     FileUtils.collect_method(:preserve) # => ["cp", "copy", "cp_r", "install"]
  #
  def self.collect_method: (Symbol opt) -> Array[String]

  # <!--
  #   rdoc-file=lib/fileutils.rb
  #   - commands()
  # -->
  # Returns an array of the string names of FileUtils methods that accept one or
  # more keyword arguments:
  #
  #     FileUtils.commands.sort.take(3) # => ["cd", "chdir", "chmod"]
  #
  def self.commands: () -> Array[String]

  # <!--
  #   rdoc-file=lib/fileutils.rb
  #   - compare_file(a, b)
  # -->
  # Returns `true` if the contents of files `a` and `b` are identical, `false`
  # otherwise.
  #
  # Arguments `a` and `b` should be [interpretable as a
  # path](rdoc-ref:FileUtils@Path+Arguments).
  #
  # FileUtils.identical? and FileUtils.cmp are aliases for FileUtils.compare_file.
  #
  # Related: FileUtils.compare_stream.
  #
  def self?.compare_file: (path a, path b) -> bool

  # <!--
  #   rdoc-file=lib/fileutils.rb
  #   - cmp(a, b)
  # -->
  #
  alias self.cmp self.compare_file

  # <!--
  #   rdoc-file=lib/fileutils.rb
  #   - cmp(a, b)
  # -->
  #
  alias cmp compare_file

  # <!--
  #   rdoc-file=lib/fileutils.rb
  #   - identical?(a, b)
  # -->
  #
  alias self.identical? self.compare_file

  # <!--
  #   rdoc-file=lib/fileutils.rb
  #   - identical?(a, b)
  # -->
  #
  alias identical? compare_file

  # <!--
  #   rdoc-file=lib/fileutils.rb
  #   - compare_stream(a, b)
  # -->
  # Returns `true` if the contents of streams `a` and `b` are identical, `false`
  # otherwise.
  #
  # Arguments `a` and `b` should be [interpretable as a
  # path](rdoc-ref:FileUtils@Path+Arguments).
  #
  # Related: FileUtils.compare_file.
  #
  def self?.compare_stream: (IO a, IO b) -> bool

  # <!--
  #   rdoc-file=lib/fileutils.rb
  #   - copy_entry(src, dest, preserve = false, dereference_root = false, remove_destination = false)
  # -->
  # Recursively copies files from `src` to `dest`.
  #
  # Arguments `src` and `dest` should be [interpretable as
  # paths](rdoc-ref:FileUtils@Path+Arguments).
  #
  # If `src` is the path to a file, copies `src` to `dest`:
  #
  #     FileUtils.touch('src0.txt')
  #     File.exist?('dest0.txt') # => false
  #     FileUtils.copy_entry('src0.txt', 'dest0.txt')
  #     File.file?('dest0.txt')  # => true
  #
  # If `src` is a directory, recursively copies `src` to `dest`:
  #
  #     tree('src1')
  #     # => src1
  #     #    |-- dir0
  #     #    |   |-- src0.txt
  #     #    |   `-- src1.txt
  #     #    `-- dir1
  #     #        |-- src2.txt
  #     #        `-- src3.txt
  #     FileUtils.copy_entry('src1', 'dest1')
  #     tree('dest1')
  #     # => dest1
  #     #    |-- dir0
  #     #    |   |-- src0.txt
  #     #    |   `-- src1.txt
  #     #    `-- dir1
  #     #        |-- src2.txt
  #     #        `-- src3.txt
  #
  # The recursive copying preserves file types for regular files, directories, and
  # symbolic links; other file types (FIFO streams, device files, etc.) are not
  # supported.
  #
  # Keyword arguments:
  #
  # *   `dereference_root: true` - if `src` is a symbolic link, follows the link.
  # *   `preserve: true` - preserves file times.
  # *   `remove_destination: true` - removes `dest` before copying files.
  #
  # Related: [methods for copying](rdoc-ref:FileUtils@Copying).
  #
  def self?.copy_entry: (path src, path dest, ?boolish preserve, ?boolish dereference_root, ?boolish remove_destination) -> void

  # <!--
  #   rdoc-file=lib/fileutils.rb
  #   - copy_file(src, dest, preserve = false, dereference = true)
  # -->
  # Copies file from `src` to `dest`, which should not be directories.
  #
  # Arguments `src` and `dest` should be [interpretable as
  # paths](rdoc-ref:FileUtils@Path+Arguments).
  #
  # Examples:
  #
  #     FileUtils.touch('src0.txt')
  #     FileUtils.copy_file('src0.txt', 'dest0.txt')
  #     File.file?('dest0.txt') # => true
  #
  # Keyword arguments:
  #
  # *   `dereference: false` - if `src` is a symbolic link, does not follow the
  #     link.
  # *   `preserve: true` - preserves file times.
  # *   `remove_destination: true` - removes `dest` before copying files.
  #
  # Related: [methods for copying](rdoc-ref:FileUtils@Copying).
  #
  def self?.copy_file: (path src, path dest, ?boolish preserve, ?boolish dereference) -> void

  # <!--
  #   rdoc-file=lib/fileutils.rb
  #   - copy_stream(src, dest)
  # -->
  # Copies IO stream `src` to IO stream `dest` via
  # [IO.copy_stream](rdoc-ref:IO.copy_stream).
  #
  # Related: [methods for copying](rdoc-ref:FileUtils@Copying).
  #
  def self?.copy_stream: (_Reader src, _Writer dest) -> void

  # <!--
  #   rdoc-file=lib/fileutils.rb
  #   - cp(src, dest, preserve: nil, noop: nil, verbose: nil)
  # -->
  # Copies files.
  #
  # Arguments `src` (a single path or an array of paths) and `dest` (a single
  # path) should be [interpretable as paths](rdoc-ref:FileUtils@Path+Arguments).
  #
  # If `src` is the path to a file and `dest` is not the path to a directory,
  # copies `src` to `dest`:
  #
  #     FileUtils.touch('src0.txt')
  #     File.exist?('dest0.txt') # => false
  #     FileUtils.cp('src0.txt', 'dest0.txt')
  #     File.file?('dest0.txt')  # => true
  #
  # If `src` is the path to a file and `dest` is the path to a directory, copies
  # `src` to `dest/src`:
  #
  #     FileUtils.touch('src1.txt')
  #     FileUtils.mkdir('dest1')
  #     FileUtils.cp('src1.txt', 'dest1')
  #     File.file?('dest1/src1.txt') # => true
  #
  # If `src` is an array of paths to files and `dest` is the path to a directory,
  # copies from each `src` to `dest`:
  #
  #     src_file_paths = ['src2.txt', 'src2.dat']
  #     FileUtils.touch(src_file_paths)
  #     FileUtils.mkdir('dest2')
  #     FileUtils.cp(src_file_paths, 'dest2')
  #     File.file?('dest2/src2.txt') # => true
  #     File.file?('dest2/src2.dat') # => true
  #
  # Keyword arguments:
  #
  # *   `preserve: true` - preserves file times.
  # *   `noop: true` - does not copy files.
  # *   `verbose: true` - prints an equivalent command:
  #
  #         FileUtils.cp('src0.txt', 'dest0.txt', noop: true, verbose: true)
  #         FileUtils.cp('src1.txt', 'dest1', noop: true, verbose: true)
  #         FileUtils.cp(src_file_paths, 'dest2', noop: true, verbose: true)
  #
  #     Output:
  #
  #         cp src0.txt dest0.txt
  #         cp src1.txt dest1
  #         cp src2.txt src2.dat dest2
  #
  # Raises an exception if `src` is a directory.
  #
  # Related: [methods for copying](rdoc-ref:FileUtils@Copying).
  #
  def self?.cp: (pathlist src, path dest, ?preserve: boolish, ?noop: boolish, ?verbose: boolish) -> void

  # <!--
  #   rdoc-file=lib/fileutils.rb
  #   - copy(src, dest, preserve: nil, noop: nil, verbose: nil)
  # -->
  #
  alias self.copy self.cp

  # <!--
  #   rdoc-file=lib/fileutils.rb
  #   - copy(src, dest, preserve: nil, noop: nil, verbose: nil)
  # -->
  #
  alias copy cp

  # <!--
  #   rdoc-file=lib/fileutils.rb
  #   - cp_lr(src, dest, noop: nil, verbose: nil, dereference_root: true, remove_destination: false)
  # -->
  # Creates [hard links](https://en.wikipedia.org/wiki/Hard_link).
  #
  # Arguments `src` (a single path or an array of paths) and `dest` (a single
  # path) should be [interpretable as paths](rdoc-ref:FileUtils@Path+Arguments).
  #
  # If `src` is the path to a directory and `dest` does not exist, creates links
  # `dest` and descendents pointing to `src` and its descendents:
  #
  #     tree('src0')
  #     # => src0
  #     #    |-- sub0
  #     #    |   |-- src0.txt
  #     #    |   `-- src1.txt
  #     #    `-- sub1
  #     #        |-- src2.txt
  #     #        `-- src3.txt
  #     File.exist?('dest0') # => false
  #     FileUtils.cp_lr('src0', 'dest0')
  #     tree('dest0')
  #     # => dest0
  #     #    |-- sub0
  #     #    |   |-- src0.txt
  #     #    |   `-- src1.txt
  #     #    `-- sub1
  #     #        |-- src2.txt
  #     #        `-- src3.txt
  #
  # If `src` and `dest` are both paths to directories, creates links `dest/src`
  # and descendents pointing to `src` and its descendents:
  #
  #     tree('src1')
  #     # => src1
  #     #    |-- sub0
  #     #    |   |-- src0.txt
  #     #    |   `-- src1.txt
  #     #    `-- sub1
  #     #        |-- src2.txt
  #     #        `-- src3.txt
  #     FileUtils.mkdir('dest1')
  #     FileUtils.cp_lr('src1', 'dest1')
  #     tree('dest1')
  #     # => dest1
  #     #    `-- src1
  #     #        |-- sub0
  #     #        |   |-- src0.txt
  #     #        |   `-- src1.txt
  #     #        `-- sub1
  #     #            |-- src2.txt
  #     #            `-- src3.txt
  #
  # If `src` is an array of paths to entries and `dest` is the path to a
  # directory, for each path `filepath` in `src`, creates a link at
  # `dest/filepath` pointing to that path:
  #
  #     tree('src2')
  #     # => src2
  #     #    |-- sub0
  #     #    |   |-- src0.txt
  #     #    |   `-- src1.txt
  #     #    `-- sub1
  #     #        |-- src2.txt
  #     #        `-- src3.txt
  #     FileUtils.mkdir('dest2')
  #     FileUtils.cp_lr(['src2/sub0', 'src2/sub1'], 'dest2')
  #     tree('dest2')
  #     # => dest2
  #     #    |-- sub0
  #     #    |   |-- src0.txt
  #     #    |   `-- src1.txt
  #     #    `-- sub1
  #     #        |-- src2.txt
  #     #        `-- src3.txt
  #
  # Keyword arguments:
  #
  # *   `dereference_root: false` - if `src` is a symbolic link, does not
  #     dereference it.
  # *   `noop: true` - does not create links.
  # *   `remove_destination: true` - removes `dest` before creating links.
  # *   `verbose: true` - prints an equivalent command:
  #
  #         FileUtils.cp_lr('src0', 'dest0', noop: true, verbose: true)
  #         FileUtils.cp_lr('src1', 'dest1', noop: true, verbose: true)
  #         FileUtils.cp_lr(['src2/sub0', 'src2/sub1'], 'dest2', noop: true, verbose: true)
  #
  #     Output:
  #
  #         cp -lr src0 dest0
  #         cp -lr src1 dest1
  #         cp -lr src2/sub0 src2/sub1 dest2
  #
  # Raises an exception if `dest` is the path to an existing file or directory and
  # keyword argument `remove_destination: true` is not given.
  #
  # Related: [methods for copying](rdoc-ref:FileUtils@Copying).
  #
  def self?.cp_lr: (pathlist src, path dest, ?noop: boolish, ?verbose: boolish, ?dereference_root: boolish, ?remove_destination: boolish) -> void

  # <!--
  #   rdoc-file=lib/fileutils.rb
  #   - cp_r(src, dest, preserve: nil, noop: nil, verbose: nil, dereference_root: true, remove_destination: nil)
  # -->
  # Recursively copies files.
  #
  # Arguments `src` (a single path or an array of paths) and `dest` (a single
  # path) should be [interpretable as paths](rdoc-ref:FileUtils@Path+Arguments).
  #
  # The mode, owner, and group are retained in the copy; to change those, use
  # FileUtils.install instead.
  #
  # If `src` is the path to a file and `dest` is not the path to a directory,
  # copies `src` to `dest`:
  #
  #     FileUtils.touch('src0.txt')
  #     File.exist?('dest0.txt') # => false
  #     FileUtils.cp_r('src0.txt', 'dest0.txt')
  #     File.file?('dest0.txt')  # => true
  #
  # If `src` is the path to a file and `dest` is the path to a directory, copies
  # `src` to `dest/src`:
  #
  #     FileUtils.touch('src1.txt')
  #     FileUtils.mkdir('dest1')
  #     FileUtils.cp_r('src1.txt', 'dest1')
  #     File.file?('dest1/src1.txt') # => true
  #
  # If `src` is the path to a directory and `dest` does not exist, recursively
  # copies `src` to `dest`:
  #
  #     tree('src2')
  #     # => src2
  #     #    |-- dir0
  #     #    |   |-- src0.txt
  #     #    |   `-- src1.txt
  #     #    `-- dir1
  #     #    |-- src2.txt
  #     #    `-- src3.txt
  #     FileUtils.exist?('dest2') # => false
  #     FileUtils.cp_r('src2', 'dest2')
  #     tree('dest2')
  #     # => dest2
  #     #    |-- dir0
  #     #    |   |-- src0.txt
  #     #    |   `-- src1.txt
  #     #    `-- dir1
  #     #    |-- src2.txt
  #     #    `-- src3.txt
  #
  # If `src` and `dest` are paths to directories, recursively copies `src` to
  # `dest/src`:
  #
  #     tree('src3')
  #     # => src3
  #     #    |-- dir0
  #     #    |   |-- src0.txt
  #     #    |   `-- src1.txt
  #     #    `-- dir1
  #     #    |-- src2.txt
  #     #    `-- src3.txt
  #     FileUtils.mkdir('dest3')
  #     FileUtils.cp_r('src3', 'dest3')
  #     tree('dest3')
  #     # => dest3
  #     #    `-- src3
  #     #      |-- dir0
  #     #      |   |-- src0.txt
  #     #      |   `-- src1.txt
  #     #      `-- dir1
  #     #          |-- src2.txt
  #     #          `-- src3.txt
  #
  # If `src` is an array of paths and `dest` is a directory, recursively copies
  # from each path in `src` to `dest`; the paths in `src` may point to files
  # and/or directories.
  #
  # Keyword arguments:
  #
  # *   `dereference_root: false` - if `src` is a symbolic link, does not
  #     dereference it.
  # *   `noop: true` - does not copy files.
  # *   `preserve: true` - preserves file times.
  # *   `remove_destination: true` - removes `dest` before copying files.
  # *   `verbose: true` - prints an equivalent command:
  #
  #         FileUtils.cp_r('src0.txt', 'dest0.txt', noop: true, verbose: true)
  #         FileUtils.cp_r('src1.txt', 'dest1', noop: true, verbose: true)
  #         FileUtils.cp_r('src2', 'dest2', noop: true, verbose: true)
  #         FileUtils.cp_r('src3', 'dest3', noop: true, verbose: true)
  #
  #     Output:
  #
  #         cp -r src0.txt dest0.txt
  #         cp -r src1.txt dest1
  #         cp -r src2 dest2
  #         cp -r src3 dest3
  #
  # Raises an exception of `src` is the path to a directory and `dest` is the path
  # to a file.
  #
  # Related: [methods for copying](rdoc-ref:FileUtils@Copying).
  #
  def self?.cp_r: (pathlist src, path dest, ?preserve: boolish, ?noop: boolish, ?verbose: boolish, ?dereference_root: boolish, ?remove_destination: boolish) -> void

  # <!--
  #   rdoc-file=lib/fileutils.rb
  #   - have_option?(mid, opt)
  # -->
  # Returns `true` if method `mid` accepts the given option `opt`, `false`
  # otherwise; the arguments may be strings or symbols:
  #
  #     FileUtils.have_option?(:chmod, :noop) # => true
  #     FileUtils.have_option?('chmod', 'secure') # => false
  #
  def self.have_option?: (Symbol mid, Symbol opt) -> bool

  # <!--
  #   rdoc-file=lib/fileutils.rb
  #   - install(src, dest, mode: nil, owner: nil, group: nil, preserve: nil, noop: nil, verbose: nil)
  # -->
  # Copies a file entry. See
  # [install(1)](https://man7.org/linux/man-pages/man1/install.1.html).
  #
  # Arguments `src` (a single path or an array of paths) and `dest` (a single
  # path) should be [interpretable as paths](rdoc-ref:FileUtils@Path+Arguments);
  #
  # If the entry at `dest` does not exist, copies from `src` to `dest`:
  #
  #     File.read('src0.txt')    # => "aaa\n"
  #     File.exist?('dest0.txt') # => false
  #     FileUtils.install('src0.txt', 'dest0.txt')
  #     File.read('dest0.txt')   # => "aaa\n"
  #
  # If `dest` is a file entry, copies from `src` to `dest`, overwriting:
  #
  #     File.read('src1.txt')  # => "aaa\n"
  #     File.read('dest1.txt') # => "bbb\n"
  #     FileUtils.install('src1.txt', 'dest1.txt')
  #     File.read('dest1.txt') # => "aaa\n"
  #
  # If `dest` is a directory entry, copies from `src` to `dest/src`, overwriting
  # if necessary:
  #
  #     File.read('src2.txt')       # => "aaa\n"
  #     File.read('dest2/src2.txt') # => "bbb\n"
  #     FileUtils.install('src2.txt', 'dest2')
  #     File.read('dest2/src2.txt') # => "aaa\n"
  #
  # If `src` is an array of paths and `dest` points to a directory, copies each
  # path `path` in `src` to `dest/path`:
  #
  #     File.file?('src3.txt') # => true
  #     File.file?('src3.dat') # => true
  #     FileUtils.mkdir('dest3')
  #     FileUtils.install(['src3.txt', 'src3.dat'], 'dest3')
  #     File.file?('dest3/src3.txt') # => true
  #     File.file?('dest3/src3.dat') # => true
  #
  # Keyword arguments:
  #
  # *   `group: *group`* - changes the group if not `nil`, using
  #     [File.chown](rdoc-ref:File.chown).
  # *   `mode: *permissions`* - changes the permissions. using
  #     [File.chmod](rdoc-ref:File.chmod).
  # *   `noop: true` - does not copy entries; returns `nil`.
  # *   `owner: *owner`* - changes the owner if not `nil`, using
  #     [File.chown](rdoc-ref:File.chown).
  # *   `preserve: true` - preserve timestamps using
  #     [File.utime](rdoc-ref:File.utime).
  # *   `verbose: true` - prints an equivalent command:
  #
  #         FileUtils.install('src0.txt', 'dest0.txt', noop: true, verbose: true)
  #         FileUtils.install('src1.txt', 'dest1.txt', noop: true, verbose: true)
  #         FileUtils.install('src2.txt', 'dest2', noop: true, verbose: true)
  #
  #     Output:
  #
  #         install -c src0.txt dest0.txt
  #         install -c src1.txt dest1.txt
  #         install -c src2.txt dest2
  #
  # Related: [methods for copying](rdoc-ref:FileUtils@Copying).
  #
  def self?.install: (path src, path dest, ?mode: mode?, ?owner: String?, ?group: String?, ?preserve: boolish, ?noop: boolish, ?verbose: boolish) -> void

  # <!--
  #   rdoc-file=lib/fileutils.rb
  #   - link_entry(src, dest, dereference_root = false, remove_destination = false)
  # -->
  # Creates [hard links](https://en.wikipedia.org/wiki/Hard_link); returns `nil`.
  #
  # Arguments `src` and `dest` should be [interpretable as
  # paths](rdoc-ref:FileUtils@Path+Arguments).
  #
  # If `src` is the path to a file and `dest` does not exist, creates a hard link
  # at `dest` pointing to `src`:
  #
  #     FileUtils.touch('src0.txt')
  #     File.exist?('dest0.txt') # => false
  #     FileUtils.link_entry('src0.txt', 'dest0.txt')
  #     File.file?('dest0.txt')  # => true
  #
  # If `src` is the path to a directory and `dest` does not exist, recursively
  # creates hard links at `dest` pointing to paths in `src`:
  #
  #     FileUtils.mkdir_p(['src1/dir0', 'src1/dir1'])
  #     src_file_paths = [
  #       'src1/dir0/t0.txt',
  #       'src1/dir0/t1.txt',
  #       'src1/dir1/t2.txt',
  #       'src1/dir1/t3.txt',
  #       ]
  #     FileUtils.touch(src_file_paths)
  #     File.directory?('dest1')        # => true
  #     FileUtils.link_entry('src1', 'dest1')
  #     File.file?('dest1/dir0/t0.txt') # => true
  #     File.file?('dest1/dir0/t1.txt') # => true
  #     File.file?('dest1/dir1/t2.txt') # => true
  #     File.file?('dest1/dir1/t3.txt') # => true
  #
  # Keyword arguments:
  #
  # *   `dereference_root: true` - dereferences `src` if it is a symbolic link.
  # *   `remove_destination: true` - removes `dest` before creating links.
  #
  # Raises an exception if `dest` is the path to an existing file or directory and
  # keyword argument `remove_destination: true` is not given.
  #
  # Related: FileUtils.ln (has different options).
  #
  def self?.link_entry: (path src, path dest, ?boolish dereference_root, ?boolish remove_destination) -> void

  # <!--
  #   rdoc-file=lib/fileutils.rb
  #   - ln(src, dest, force: nil, noop: nil, verbose: nil)
  # -->
  # Creates [hard links](https://en.wikipedia.org/wiki/Hard_link).
  #
  # Arguments `src` (a single path or an array of paths) and `dest` (a single
  # path) should be [interpretable as paths](rdoc-ref:FileUtils@Path+Arguments).
  #
  # When `src` is the path to an existing file and `dest` is the path to a
  # non-existent file, creates a hard link at `dest` pointing to `src`; returns
  # zero:
  #
  #     Dir.children('tmp0/')                    # => ["t.txt"]
  #     Dir.children('tmp1/')                    # => []
  #     FileUtils.ln('tmp0/t.txt', 'tmp1/t.lnk') # => 0
  #     Dir.children('tmp1/')                    # => ["t.lnk"]
  #
  # When `src` is the path to an existing file and `dest` is the path to an
  # existing directory, creates a hard link at `dest/src` pointing to `src`;
  # returns zero:
  #
  #     Dir.children('tmp2')               # => ["t.dat"]
  #     Dir.children('tmp3')               # => []
  #     FileUtils.ln('tmp2/t.dat', 'tmp3') # => 0
  #     Dir.children('tmp3')               # => ["t.dat"]
  #
  # When `src` is an array of paths to existing files and `dest` is the path to an
  # existing directory, then for each path `target` in `src`, creates a hard link
  # at `dest/target` pointing to `target`; returns `src`:
  #
  #     Dir.children('tmp4/')                               # => []
  #     FileUtils.ln(['tmp0/t.txt', 'tmp2/t.dat'], 'tmp4/') # => ["tmp0/t.txt", "tmp2/t.dat"]
  #     Dir.children('tmp4/')                               # => ["t.dat", "t.txt"]
  #
  # Keyword arguments:
  #
  # *   `force: true` - overwrites `dest` if it exists.
  # *   `noop: true` - does not create links.
  # *   `verbose: true` - prints an equivalent command:
  #
  #         FileUtils.ln('tmp0/t.txt', 'tmp1/t.lnk', verbose: true)
  #         FileUtils.ln('tmp2/t.dat', 'tmp3', verbose: true)
  #         FileUtils.ln(['tmp0/t.txt', 'tmp2/t.dat'], 'tmp4/', verbose: true)
  #
  #     Output:
  #
  #         ln tmp0/t.txt tmp1/t.lnk
  #         ln tmp2/t.dat tmp3
  #         ln tmp0/t.txt tmp2/t.dat tmp4/
  #
  # Raises an exception if `dest` is the path to an existing file and keyword
  # argument `force` is not `true`.
  #
  # Related: FileUtils.link_entry (has different options).
  #
  def self?.ln: (pathlist src, path dest, ?force: boolish, ?noop: boolish, ?verbose: boolish) -> void

  # <!--
  #   rdoc-file=lib/fileutils.rb
  #   - link(src, dest, force: nil, noop: nil, verbose: nil)
  # -->
  #
  alias self.link self.ln

  # <!--
  #   rdoc-file=lib/fileutils.rb
  #   - link(src, dest, force: nil, noop: nil, verbose: nil)
  # -->
  #
  alias link ln

  # <!--
  #   rdoc-file=lib/fileutils.rb
  #   - ln_s(src, dest, force: nil, relative: false, target_directory: true, noop: nil, verbose: nil)
  # -->
  # Creates [symbolic links](https://en.wikipedia.org/wiki/Symbolic_link).
  #
  # Arguments `src` (a single path or an array of paths) and `dest` (a single
  # path) should be [interpretable as paths](rdoc-ref:FileUtils@Path+Arguments).
  #
  # If `src` is the path to an existing file:
  #
  # *   When `dest` is the path to a non-existent file, creates a symbolic link at
  #     `dest` pointing to `src`:
  #
  #         FileUtils.touch('src0.txt')
  #         File.exist?('dest0.txt')   # => false
  #         FileUtils.ln_s('src0.txt', 'dest0.txt')
  #         File.symlink?('dest0.txt') # => true
  #
  # *   When `dest` is the path to an existing file, creates a symbolic link at
  #     `dest` pointing to `src` if and only if keyword argument `force: true` is
  #     given (raises an exception otherwise):
  #
  #         FileUtils.touch('src1.txt')
  #         FileUtils.touch('dest1.txt')
  #         FileUtils.ln_s('src1.txt', 'dest1.txt', force: true)
  #         FileTest.symlink?('dest1.txt') # => true
  #
  #         FileUtils.ln_s('src1.txt', 'dest1.txt') # Raises Errno::EEXIST.
  #
  # If `dest` is the path to a directory, creates a symbolic link at `dest/src`
  # pointing to `src`:
  #
  #     FileUtils.touch('src2.txt')
  #     FileUtils.mkdir('destdir2')
  #     FileUtils.ln_s('src2.txt', 'destdir2')
  #     File.symlink?('destdir2/src2.txt') # => true
  #
  # If `src` is an array of paths to existing files and `dest` is a directory, for
  # each child `child` in `src` creates a symbolic link `dest/child` pointing to
  # `child`:
  #
  #     FileUtils.mkdir('srcdir3')
  #     FileUtils.touch('srcdir3/src0.txt')
  #     FileUtils.touch('srcdir3/src1.txt')
  #     FileUtils.mkdir('destdir3')
  #     FileUtils.ln_s(['srcdir3/src0.txt', 'srcdir3/src1.txt'], 'destdir3')
  #     File.symlink?('destdir3/src0.txt') # => true
  #     File.symlink?('destdir3/src1.txt') # => true
  #
  # Keyword arguments:
  #
  # *   `force: true` - overwrites `dest` if it exists.
  # *   `relative: false` - create links relative to `dest`.
  # *   `noop: true` - does not create links.
  # *   `verbose: true` - prints an equivalent command:
  #
  #         FileUtils.ln_s('src0.txt', 'dest0.txt', noop: true, verbose: true)
  #         FileUtils.ln_s('src1.txt', 'destdir1', noop: true, verbose: true)
  #         FileUtils.ln_s('src2.txt', 'dest2.txt', force: true, noop: true, verbose: true)
  #         FileUtils.ln_s(['srcdir3/src0.txt', 'srcdir3/src1.txt'], 'destdir3', noop: true, verbose: true)
  #
  #     Output:
  #
  #         ln -s src0.txt dest0.txt
  #         ln -s src1.txt destdir1
  #         ln -sf src2.txt dest2.txt
  #         ln -s srcdir3/src0.txt srcdir3/src1.txt destdir3
  #
  # Related: FileUtils.ln_sf.
  #
  def self?.ln_s: (pathlist src, path dest, ?force: boolish, ?relative: boolish, ?target_directory: boolish, ?noop: boolish, ?verbose: boolish) -> void

  # <!--
  #   rdoc-file=lib/fileutils.rb
  #   - symlink(src, dest, force: nil, relative: false, target_directory: true, noop: nil, verbose: nil)
  # -->
  #
  alias self.symlink self.ln_s

  # <!--
  #   rdoc-file=lib/fileutils.rb
  #   - symlink(src, dest, force: nil, relative: false, target_directory: true, noop: nil, verbose: nil)
  # -->
  #
  alias symlink ln_s

  # <!--
  #   rdoc-file=lib/fileutils.rb
  #   - ln_sf(src, dest, noop: nil, verbose: nil)
  # -->
  # Like FileUtils.ln_s, but always with keyword argument `force: true` given.
  #
  def self?.ln_sf: (pathlist src, path dest, ?noop: boolish, ?verbose: boolish) -> void

  # <!--
  #   rdoc-file=lib/fileutils.rb
  #   - ln_sr(src, dest, target_directory: true, force: nil, noop: nil, verbose: nil)
  # -->
  # Like FileUtils.ln_s, but create links relative to `dest`.
  #
  def self?.ln_sr: (pathlist src, path dest, ?target_directory: boolish, ?noop: boolish, ?verbose: boolish) -> void

  # <!--
  #   rdoc-file=lib/fileutils.rb
  #   - mkdir(list, mode: nil, noop: nil, verbose: nil)
  # -->
  # Creates directories at the paths in the given `list` (a single path or an
  # array of paths); returns `list` if it is an array, `[list]` otherwise.
  #
  # Argument `list` or its elements should be [interpretable as
  # paths](rdoc-ref:FileUtils@Path+Arguments).
  #
  # With no keyword arguments, creates a directory at each `path` in `list` by
  # calling: `Dir.mkdir(path, mode)`; see [Dir.mkdir](rdoc-ref:Dir.mkdir):
  #
  #     FileUtils.mkdir(%w[tmp0 tmp1]) # => ["tmp0", "tmp1"]
  #     FileUtils.mkdir('tmp4')        # => ["tmp4"]
  #
  # Keyword arguments:
  #
  # *   `mode: *mode`* - also calls `File.chmod(mode, path)`; see
  #     [File.chmod](rdoc-ref:File.chmod).
  # *   `noop: true` - does not create directories.
  # *   `verbose: true` - prints an equivalent command:
  #
  #         FileUtils.mkdir(%w[tmp0 tmp1], verbose: true)
  #         FileUtils.mkdir(%w[tmp2 tmp3], mode: 0700, verbose: true)
  #
  #     Output:
  #
  #         mkdir tmp0 tmp1
  #         mkdir -m 700 tmp2 tmp3
  #
  # Raises an exception if any path points to an existing file or directory, or if
  # for any reason a directory cannot be created.
  #
  # Related: FileUtils.mkdir_p.
  #
  def self?.mkdir: (pathlist list, ?mode: Integer?, ?noop: boolish, ?verbose: boolish) -> void

  # <!--
  #   rdoc-file=lib/fileutils.rb
  #   - mkdir_p(list, mode: nil, noop: nil, verbose: nil)
  # -->
  # Creates directories at the paths in the given `list` (a single path or an
  # array of paths), also creating ancestor directories as needed; returns `list`
  # if it is an array, `[list]` otherwise.
  #
  # Argument `list` or its elements should be [interpretable as
  # paths](rdoc-ref:FileUtils@Path+Arguments).
  #
  # With no keyword arguments, creates a directory at each `path` in `list`, along
  # with any needed ancestor directories, by calling: `Dir.mkdir(path, mode)`; see
  # [Dir.mkdir](rdoc-ref:Dir.mkdir):
  #
  #     FileUtils.mkdir_p(%w[tmp0/tmp1 tmp2/tmp3]) # => ["tmp0/tmp1", "tmp2/tmp3"]
  #     FileUtils.mkdir_p('tmp4/tmp5')             # => ["tmp4/tmp5"]
  #
  # Keyword arguments:
  #
  # *   `mode: *mode`* - also calls `File.chmod(mode, path)`; see
  #     [File.chmod](rdoc-ref:File.chmod).
  # *   `noop: true` - does not create directories.
  # *   `verbose: true` - prints an equivalent command:
  #
  #         FileUtils.mkdir_p(%w[tmp0 tmp1], verbose: true)
  #         FileUtils.mkdir_p(%w[tmp2 tmp3], mode: 0700, verbose: true)
  #
  #     Output:
  #
  #         mkdir -p tmp0 tmp1
  #         mkdir -p -m 700 tmp2 tmp3
  #
  # Raises an exception if for any reason a directory cannot be created.
  #
  # FileUtils.mkpath and FileUtils.makedirs are aliases for FileUtils.mkdir_p.
  #
  # Related: FileUtils.mkdir.
  #
  def self?.mkdir_p: (pathlist list, ?mode: mode?, ?noop: boolish, ?verbose: boolish) -> void

  # <!--
  #   rdoc-file=lib/fileutils.rb
  #   - makedirs(list, mode: nil, noop: nil, verbose: nil)
  # -->
  #
  alias self.makedirs self.mkdir_p

  # <!--
  #   rdoc-file=lib/fileutils.rb
  #   - makedirs(list, mode: nil, noop: nil, verbose: nil)
  # -->
  #
  alias makedirs mkdir_p

  # <!--
  #   rdoc-file=lib/fileutils.rb
  #   - mkpath(list, mode: nil, noop: nil, verbose: nil)
  # -->
  #
  alias self.mkpath self.mkdir_p

  # <!--
  #   rdoc-file=lib/fileutils.rb
  #   - mkpath(list, mode: nil, noop: nil, verbose: nil)
  # -->
  #
  alias mkpath mkdir_p

  # <!--
  #   rdoc-file=lib/fileutils.rb
  #   - mv(src, dest, force: nil, noop: nil, verbose: nil, secure: nil)
  # -->
  # Moves entries.
  #
  # Arguments `src` (a single path or an array of paths) and `dest` (a single
  # path) should be [interpretable as paths](rdoc-ref:FileUtils@Path+Arguments).
  #
  # If `src` and `dest` are on different file systems, first copies, then removes
  # `src`.
  #
  # May cause a local vulnerability if not called with keyword argument `secure:
  # true`; see [Avoiding the TOCTTOU
  # Vulnerability](rdoc-ref:FileUtils@Avoiding+the+TOCTTOU+Vulnerability).
  #
  # If `src` is the path to a single file or directory and `dest` does not exist,
  # moves `src` to `dest`:
  #
  #     tree('src0')
  #     # => src0
  #     #    |-- src0.txt
  #     #    `-- src1.txt
  #     File.exist?('dest0') # => false
  #     FileUtils.mv('src0', 'dest0')
  #     File.exist?('src0')  # => false
  #     tree('dest0')
  #     # => dest0
  #     #    |-- src0.txt
  #     #    `-- src1.txt
  #
  # If `src` is an array of paths to files and directories and `dest` is the path
  # to a directory, copies from each path in the array to `dest`:
  #
  #     File.file?('src1.txt') # => true
  #     tree('src1')
  #     # => src1
  #     #    |-- src.dat
  #     #    `-- src.txt
  #     Dir.empty?('dest1')    # => true
  #     FileUtils.mv(['src1.txt', 'src1'], 'dest1')
  #     tree('dest1')
  #     # => dest1
  #     #    |-- src1
  #     #    |   |-- src.dat
  #     #    |   `-- src.txt
  #     #    `-- src1.txt
  #
  # Keyword arguments:
  #
  # *   `force: true` - if the move includes removing `src` (that is, if `src` and
  #     `dest` are on different file systems), ignores raised exceptions of
  #     StandardError and its descendants.
  # *   `noop: true` - does not move files.
  # *   `secure: true` - removes `src` securely; see details at
  #     FileUtils.remove_entry_secure.
  # *   `verbose: true` - prints an equivalent command:
  #
  #         FileUtils.mv('src0', 'dest0', noop: true, verbose: true)
  #         FileUtils.mv(['src1.txt', 'src1'], 'dest1', noop: true, verbose: true)
  #
  #     Output:
  #
  #         mv src0 dest0
  #         mv src1.txt src1 dest1
  #
  def self?.mv: (pathlist src, path dest, ?force: boolish, ?noop: boolish, ?verbose: boolish, ?secure: boolish) -> void

  # <!--
  #   rdoc-file=lib/fileutils.rb
  #   - move(src, dest, force: nil, noop: nil, verbose: nil, secure: nil)
  # -->
  #
  alias self.move self.mv

  # <!--
  #   rdoc-file=lib/fileutils.rb
  #   - move(src, dest, force: nil, noop: nil, verbose: nil, secure: nil)
  # -->
  #
  alias move mv

  # <!--
  #   rdoc-file=lib/fileutils.rb
  #   - options()
  # -->
  # Returns an array of the string keyword names:
  #
  #     FileUtils.options.take(3) # => ["noop", "verbose", "force"]
  #
  def self.options: () -> Array[String]

  # <!--
  #   rdoc-file=lib/fileutils.rb
  #   - options_of(mid)
  # -->
  # Returns an array of the string keyword name for method `mid`; the argument may
  # be a string or a symbol:
  #
  #     FileUtils.options_of(:rm) # => ["force", "noop", "verbose"]
  #     FileUtils.options_of('mv') # => ["force", "noop", "verbose", "secure"]
  #
  def self.options_of: (Symbol mid) -> Array[String]

  # <!--
  #   rdoc-file=lib/fileutils.rb
  #   - pwd()
  # -->
  # Returns a string containing the path to the current directory:
  #
  #     FileUtils.pwd # => "/rdoc/fileutils"
  #
  # Related: FileUtils.cd.
  #
  def self?.pwd: () -> String

  # <!--
  #   rdoc-file=lib/fileutils.rb
  #   - getwd()
  # -->
  #
  alias self.getwd self.pwd

  # <!--
  #   rdoc-file=lib/fileutils.rb
  #   - getwd()
  # -->
  #
  alias getwd pwd

  # <!--
  #   rdoc-file=lib/fileutils.rb
  #   - remove_dir(path, force = false)
  # -->
  # Recursively removes the directory entry given by `path`, which should be the
  # entry for a regular file, a symbolic link, or a directory.
  #
  # Argument `path` should be [interpretable as a
  # path](rdoc-ref:FileUtils@Path+Arguments).
  #
  # Optional argument `force` specifies whether to ignore raised exceptions of
  # StandardError and its descendants.
  #
  # Related: [methods for deleting](rdoc-ref:FileUtils@Deleting).
  #
  def self?.remove_dir: (path path, ?boolish force) -> void

  # <!--
  #   rdoc-file=lib/fileutils.rb
  #   - remove_entry(path, force = false)
  # -->
  # Removes the entry given by `path`, which should be the entry for a regular
  # file, a symbolic link, or a directory.
  #
  # Argument `path` should be [interpretable as a
  # path](rdoc-ref:FileUtils@Path+Arguments).
  #
  # Optional argument `force` specifies whether to ignore raised exceptions of
  # StandardError and its descendants.
  #
  # Related: FileUtils.remove_entry_secure.
  #
  def self?.remove_entry: (path path, ?boolish force) -> void

  # <!--
  #   rdoc-file=lib/fileutils.rb
  #   - remove_entry_secure(path, force = false)
  # -->
  # Securely removes the entry given by `path`, which should be the entry for a
  # regular file, a symbolic link, or a directory.
  #
  # Argument `path` should be [interpretable as a
  # path](rdoc-ref:FileUtils@Path+Arguments).
  #
  # Avoids a local vulnerability that can exist in certain circumstances; see
  # [Avoiding the TOCTTOU
  # Vulnerability](rdoc-ref:FileUtils@Avoiding+the+TOCTTOU+Vulnerability).
  #
  # Optional argument `force` specifies whether to ignore raised exceptions of
  # StandardError and its descendants.
  #
  # Related: [methods for deleting](rdoc-ref:FileUtils@Deleting).
  #
  def self?.remove_entry_secure: (path path, ?boolish force) -> void

  # <!--
  #   rdoc-file=lib/fileutils.rb
  #   - remove_file(path, force = false)
  # -->
  # Removes the file entry given by `path`, which should be the entry for a
  # regular file or a symbolic link.
  #
  # Argument `path` should be [interpretable as a
  # path](rdoc-ref:FileUtils@Path+Arguments).
  #
  # Optional argument `force` specifies whether to ignore raised exceptions of
  # StandardError and its descendants.
  #
  # Related: [methods for deleting](rdoc-ref:FileUtils@Deleting).
  #
  def self?.remove_file: (path path, ?boolish force) -> void

  # <!--
  #   rdoc-file=lib/fileutils.rb
  #   - rm(list, force: nil, noop: nil, verbose: nil)
  # -->
  # Removes entries at the paths in the given `list` (a single path or an array of
  # paths) returns `list`, if it is an array, `[list]` otherwise.
  #
  # Argument `list` or its elements should be [interpretable as
  # paths](rdoc-ref:FileUtils@Path+Arguments).
  #
  # With no keyword arguments, removes files at the paths given in `list`:
  #
  #     FileUtils.touch(['src0.txt', 'src0.dat'])
  #     FileUtils.rm(['src0.dat', 'src0.txt']) # => ["src0.dat", "src0.txt"]
  #
  # Keyword arguments:
  #
  # *   `force: true` - ignores raised exceptions of StandardError and its
  #     descendants.
  # *   `noop: true` - does not remove files; returns `nil`.
  # *   `verbose: true` - prints an equivalent command:
  #
  #         FileUtils.rm(['src0.dat', 'src0.txt'], noop: true, verbose: true)
  #
  #     Output:
  #
  #         rm src0.dat src0.txt
  #
  # Related: [methods for deleting](rdoc-ref:FileUtils@Deleting).
  #
  def self?.rm: (pathlist list, ?force: boolish, ?noop: boolish, ?verbose: boolish) -> void

  # <!--
  #   rdoc-file=lib/fileutils.rb
  #   - remove(list, force: nil, noop: nil, verbose: nil)
  # -->
  #
  alias self.remove self.rm

  # <!--
  #   rdoc-file=lib/fileutils.rb
  #   - remove(list, force: nil, noop: nil, verbose: nil)
  # -->
  #
  alias remove rm

  # <!--
  #   rdoc-file=lib/fileutils.rb
  #   - rm_f(list, noop: nil, verbose: nil)
  # -->
  # Equivalent to:
  #
  #     FileUtils.rm(list, force: true, **kwargs)
  #
  # Argument `list` (a single path or an array of paths) should be [interpretable
  # as paths](rdoc-ref:FileUtils@Path+Arguments).
  #
  # See FileUtils.rm for keyword arguments.
  #
  # Related: [methods for deleting](rdoc-ref:FileUtils@Deleting).
  #
  def self?.rm_f: (pathlist list, ?noop: boolish, ?verbose: boolish) -> void

  # <!--
  #   rdoc-file=lib/fileutils.rb
  #   - safe_unlink(list, noop: nil, verbose: nil)
  # -->
  #
  alias self.safe_unlink self.rm_f

  # <!--
  #   rdoc-file=lib/fileutils.rb
  #   - safe_unlink(list, noop: nil, verbose: nil)
  # -->
  #
  alias safe_unlink rm_f

  # <!--
  #   rdoc-file=lib/fileutils.rb
  #   - rm_r(list, force: nil, noop: nil, verbose: nil, secure: nil)
  # -->
  # Removes entries at the paths in the given `list` (a single path or an array of
  # paths); returns `list`, if it is an array, `[list]` otherwise.
  #
  # Argument `list` or its elements should be [interpretable as
  # paths](rdoc-ref:FileUtils@Path+Arguments).
  #
  # May cause a local vulnerability if not called with keyword argument `secure:
  # true`; see [Avoiding the TOCTTOU
  # Vulnerability](rdoc-ref:FileUtils@Avoiding+the+TOCTTOU+Vulnerability).
  #
  # For each file path, removes the file at that path:
  #
  #     FileUtils.touch(['src0.txt', 'src0.dat'])
  #     FileUtils.rm_r(['src0.dat', 'src0.txt'])
  #     File.exist?('src0.txt') # => false
  #     File.exist?('src0.dat') # => false
  #
  # For each directory path, recursively removes files and directories:
  #
  #     tree('src1')
  #     # => src1
  #     #    |-- dir0
  #     #    |   |-- src0.txt
  #     #    |   `-- src1.txt
  #     #    `-- dir1
  #     #        |-- src2.txt
  #     #        `-- src3.txt
  #     FileUtils.rm_r('src1')
  #     File.exist?('src1') # => false
  #
  # Keyword arguments:
  #
  # *   `force: true` - ignores raised exceptions of StandardError and its
  #     descendants.
  # *   `noop: true` - does not remove entries; returns `nil`.
  # *   `secure: true` - removes `src` securely; see details at
  #     FileUtils.remove_entry_secure.
  # *   `verbose: true` - prints an equivalent command:
  #
  #         FileUtils.rm_r(['src0.dat', 'src0.txt'], noop: true, verbose: true)
  #         FileUtils.rm_r('src1', noop: true, verbose: true)
  #
  #     Output:
  #
  #         rm -r src0.dat src0.txt
  #         rm -r src1
  #
  # Related: [methods for deleting](rdoc-ref:FileUtils@Deleting).
  #
  def self?.rm_r: (pathlist list, ?force: boolish, ?noop: boolish, ?verbose: boolish, ?secure: boolish) -> void

  # <!--
  #   rdoc-file=lib/fileutils.rb
  #   - rm_rf(list, noop: nil, verbose: nil, secure: nil)
  # -->
  # Equivalent to:
  #
  #     FileUtils.rm_r(list, force: true, **kwargs)
  #
  # Argument `list` or its elements should be [interpretable as
  # paths](rdoc-ref:FileUtils@Path+Arguments).
  #
  # May cause a local vulnerability if not called with keyword argument `secure:
  # true`; see [Avoiding the TOCTTOU
  # Vulnerability](rdoc-ref:FileUtils@Avoiding+the+TOCTTOU+Vulnerability).
  #
  # See FileUtils.rm_r for keyword arguments.
  #
  # Related: [methods for deleting](rdoc-ref:FileUtils@Deleting).
  #
  def self?.rm_rf: (pathlist list, ?noop: boolish, ?verbose: boolish, ?secure: boolish) -> void

  # <!--
  #   rdoc-file=lib/fileutils.rb
  #   - rmtree(list, noop: nil, verbose: nil, secure: nil)
  # -->
  #
  alias self.rmtree self.rm_rf

  # <!--
  #   rdoc-file=lib/fileutils.rb
  #   - rmtree(list, noop: nil, verbose: nil, secure: nil)
  # -->
  #
  alias rmtree rm_rf

  # <!--
  #   rdoc-file=lib/fileutils.rb
  #   - rmdir(list, parents: nil, noop: nil, verbose: nil)
  # -->
  # Removes directories at the paths in the given `list` (a single path or an
  # array of paths); returns `list`, if it is an array, `[list]` otherwise.
  #
  # Argument `list` or its elements should be [interpretable as
  # paths](rdoc-ref:FileUtils@Path+Arguments).
  #
  # With no keyword arguments, removes the directory at each `path` in `list`, by
  # calling: `Dir.rmdir(path)`; see [Dir.rmdir](rdoc-ref:Dir.rmdir):
  #
  #     FileUtils.rmdir(%w[tmp0/tmp1 tmp2/tmp3]) # => ["tmp0/tmp1", "tmp2/tmp3"]
  #     FileUtils.rmdir('tmp4/tmp5')             # => ["tmp4/tmp5"]
  #
  # Keyword arguments:
  #
  # *   `parents: true` - removes successive ancestor directories if empty.
  # *   `noop: true` - does not remove directories.
  # *   `verbose: true` - prints an equivalent command:
  #
  #         FileUtils.rmdir(%w[tmp0/tmp1 tmp2/tmp3], parents: true, verbose: true)
  #         FileUtils.rmdir('tmp4/tmp5', parents: true, verbose: true)
  #
  #     Output:
  #
  #         rmdir -p tmp0/tmp1 tmp2/tmp3
  #         rmdir -p tmp4/tmp5
  #
  # Raises an exception if a directory does not exist or if for any reason a
  # directory cannot be removed.
  #
  # Related: [methods for deleting](rdoc-ref:FileUtils@Deleting).
  #
  def self?.rmdir: (pathlist list, ?parents: boolish, ?noop: boolish, ?verbose: boolish) -> void

  # <!--
  #   rdoc-file=lib/fileutils.rb
  #   - touch(list, noop: nil, verbose: nil, mtime: nil, nocreate: nil)
  # -->
  # Updates modification times (mtime) and access times (atime) of the entries
  # given by the paths in `list` (a single path or an array of paths); returns
  # `list` if it is an array, `[list]` otherwise.
  #
  # By default, creates an empty file for any path to a non-existent entry; use
  # keyword argument `nocreate` to raise an exception instead.
  #
  # Argument `list` or its elements should be [interpretable as
  # paths](rdoc-ref:FileUtils@Path+Arguments).
  #
  # Examples:
  #
  #     # Single path.
  #     f = File.new('src0.txt') # Existing file.
  #     f.atime # => 2022-06-10 11:11:21.200277 -0700
  #     f.mtime # => 2022-06-10 11:11:21.200277 -0700
  #     FileUtils.touch('src0.txt')
  #     f = File.new('src0.txt')
  #     f.atime # => 2022-06-11 08:28:09.8185343 -0700
  #     f.mtime # => 2022-06-11 08:28:09.8185343 -0700
  #
  #     # Array of paths.
  #     FileUtils.touch(['src0.txt', 'src0.dat'])
  #
  # Keyword arguments:
  #
  # *   `mtime: *time`* - sets the entry's mtime to the given time, instead of the
  #     current time.
  # *   `nocreate: true` - raises an exception if the entry does not exist.
  # *   `noop: true` - does not touch entries; returns `nil`.
  # *   `verbose: true` - prints an equivalent command:
  #
  #         FileUtils.touch('src0.txt', noop: true, verbose: true)
  #         FileUtils.touch(['src0.txt', 'src0.dat'], noop: true, verbose: true)
  #         FileUtils.touch(path, noop: true, verbose: true)
  #
  #     Output:
  #
  #         touch src0.txt
  #         touch src0.txt src0.dat
  #         touch src0.txt
  #
  # Related: FileUtils.uptodate?.
  #
  def self?.touch: (pathlist list, ?noop: boolish, ?verbose: boolish, ?mtime: (Time | Numeric)?, ?nocreate: boolish) -> void

  # <!--
  #   rdoc-file=lib/fileutils.rb
  #   - uptodate?(new, old_list)
  # -->
  # Returns `true` if the file at path `new` is newer than all the files at paths
  # in array `old_list`; `false` otherwise.
  #
  # Argument `new` and the elements of `old_list` should be [interpretable as
  # paths](rdoc-ref:FileUtils@Path+Arguments):
  #
  #     FileUtils.uptodate?('Rakefile', ['Gemfile', 'README.md']) # => true
  #     FileUtils.uptodate?('Gemfile', ['Rakefile', 'README.md']) # => false
  #
  # A non-existent file is considered to be infinitely old.
  #
  # Related: FileUtils.touch.
  #
  def self?.uptodate?: (path new, _Each[path] old_list) -> bool
end
