Module: FileUtils
Overview
Namespace for file utility methods for copying, moving, removing, etc.
What’s Here
First, what’s elsewhere. Module FileUtils:
-
Inherits from class Object.
-
Supplements class File (but is not included or extended there).
Here, module FileUtils provides methods that are useful for:
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, 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, 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 and 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:
Defined Under Namespace
Modules: DryRun, LowMethods, NoWrite, StreamUtils_, Verbose Classes: Entry_
Constant Summary collapse
- VERSION =
The version number.
"1.7.3"
Class Method Summary collapse
-
.cd(dir, verbose: nil, &block) ⇒ Object
Changes the working directory to the given
dir
, which should be interpretable as a path:. -
.chdir ⇒ Object
Changes the working directory to the given
dir
, which should be interpretable as a path:. -
.chmod(mode, list, noop: nil, verbose: nil) ⇒ Object
Changes permissions on the entries at the paths given in
list
(a single path or an array of paths) to the permissions given bymode
; returnslist
if it is an array,[list]
otherwise:. -
.chmod_R(mode, list, noop: nil, verbose: nil, force: nil) ⇒ Object
Like FileUtils.chmod, but changes permissions recursively.
-
.chown(user, group, list, noop: nil, verbose: nil) ⇒ Object
Changes the owner and group on the entries at the paths given in
list
(a single path or an array of paths) to the givenuser
andgroup
; returnslist
if it is an array,[list]
otherwise:. -
.chown_R(user, group, list, noop: nil, verbose: nil, force: nil) ⇒ Object
Like FileUtils.chown, but changes owner and group recursively.
-
.cmp ⇒ Object
Returns
true
if the contents of filesa
andb
are identical,false
otherwise. -
.collect_method(opt) ⇒ Object
Returns an array of the string method names of the methods that accept the given keyword option
opt
; the argument must be a symbol:. -
.commands ⇒ Object
Returns an array of the string names of FileUtils methods that accept one or more keyword arguments:.
-
.compare_file(a, b) ⇒ Object
Returns
true
if the contents of filesa
andb
are identical,false
otherwise. -
.compare_stream(a, b) ⇒ Object
Returns
true
if the contents of streamsa
andb
are identical,false
otherwise. -
.copy ⇒ Object
Copies files.
-
.copy_entry(src, dest, preserve = false, dereference_root = false, remove_destination = false) ⇒ Object
Recursively copies files from
src
todest
. -
.copy_file(src, dest, preserve = false, dereference = true) ⇒ Object
Copies file from
src
todest
, which should not be directories. -
.copy_stream(src, dest) ⇒ Object
Copies IO stream
src
to IO streamdest
via IO.copy_stream. -
.cp(src, dest, preserve: nil, noop: nil, verbose: nil) ⇒ Object
Copies files.
-
.cp_lr(src, dest, noop: nil, verbose: nil, dereference_root: true, remove_destination: false) ⇒ Object
Creates hard links.
-
.cp_r(src, dest, preserve: nil, noop: nil, verbose: nil, dereference_root: true, remove_destination: nil) ⇒ Object
Recursively copies files.
-
.getwd ⇒ Object
Returns a string containing the path to the current directory:.
-
.have_option?(mid, opt) ⇒ Boolean
Returns
true
if methodmid
accepts the given optionopt
,false
otherwise; the arguments may be strings or symbols:. -
.identical? ⇒ Object
Returns
true
if the contents of filesa
andb
are identical,false
otherwise. -
.install(src, dest, mode: nil, owner: nil, group: nil, preserve: nil, noop: nil, verbose: nil) ⇒ Object
Copies a file entry.
-
.link ⇒ Object
Creates hard links.
-
.link_entry(src, dest, dereference_root = false, remove_destination = false) ⇒ Object
Creates hard links; returns
nil
. -
.ln(src, dest, force: nil, noop: nil, verbose: nil) ⇒ Object
Creates hard links.
-
.ln_s(src, dest, force: nil, relative: false, target_directory: true, noop: nil, verbose: nil) ⇒ Object
Creates symbolic links.
-
.ln_sf(src, dest, noop: nil, verbose: nil) ⇒ Object
Like FileUtils.ln_s, but always with keyword argument
force: true
given. -
.ln_sr(src, dest, target_directory: true, force: nil, noop: nil, verbose: nil) ⇒ Object
Like FileUtils.ln_s, but create links relative to
dest
. -
.makedirs ⇒ Object
Creates directories at the paths in the given
list
(a single path or an array of paths), also creating ancestor directories as needed; returnslist
if it is an array,[list]
otherwise. -
.mkdir(list, mode: nil, noop: nil, verbose: nil) ⇒ Object
Creates directories at the paths in the given
list
(a single path or an array of paths); returnslist
if it is an array,[list]
otherwise. -
.mkdir_p(list, mode: nil, noop: nil, verbose: nil) ⇒ Object
Creates directories at the paths in the given
list
(a single path or an array of paths), also creating ancestor directories as needed; returnslist
if it is an array,[list]
otherwise. -
.mkpath ⇒ Object
Creates directories at the paths in the given
list
(a single path or an array of paths), also creating ancestor directories as needed; returnslist
if it is an array,[list]
otherwise. -
.move ⇒ Object
Moves entries.
-
.mv(src, dest, force: nil, noop: nil, verbose: nil, secure: nil) ⇒ Object
Moves entries.
-
.options ⇒ Object
Returns an array of the string keyword names:.
-
.options_of(mid) ⇒ Object
Returns an array of the string keyword name for method
mid
; the argument may be a string or a symbol:. -
.private_module_function(name) ⇒ Object
:nodoc:.
-
.pwd ⇒ Object
Returns a string containing the path to the current directory:.
-
.remove ⇒ Object
Removes entries at the paths in the given
list
(a single path or an array of paths) returnslist
, if it is an array,[list]
otherwise. -
.remove_dir(path, force = false) ⇒ Object
Recursively removes the directory entry given by
path
, which should be the entry for a regular file, a symbolic link, or a directory. -
.remove_entry(path, force = false) ⇒ Object
Removes the entry given by
path
, which should be the entry for a regular file, a symbolic link, or a directory. -
.remove_entry_secure(path, force = false) ⇒ Object
Securely removes the entry given by
path
, which should be the entry for a regular file, a symbolic link, or a directory. -
.remove_file(path, force = false) ⇒ Object
Removes the file entry given by
path
, which should be the entry for a regular file or a symbolic link. -
.rm(list, force: nil, noop: nil, verbose: nil) ⇒ Object
Removes entries at the paths in the given
list
(a single path or an array of paths) returnslist
, if it is an array,[list]
otherwise. -
.rm_f(list, noop: nil, verbose: nil) ⇒ Object
Equivalent to:.
-
.rm_r(list, force: nil, noop: nil, verbose: nil, secure: nil) ⇒ Object
Removes entries at the paths in the given
list
(a single path or an array of paths); returnslist
, if it is an array,[list]
otherwise. -
.rm_rf(list, noop: nil, verbose: nil, secure: nil) ⇒ Object
Equivalent to:.
-
.rmdir(list, parents: nil, noop: nil, verbose: nil) ⇒ Object
Removes directories at the paths in the given
list
(a single path or an array of paths); returnslist
, if it is an array,[list]
otherwise. -
.rmtree ⇒ Object
Equivalent to:.
-
.safe_unlink ⇒ Object
Equivalent to:.
-
.symlink ⇒ Object
Creates symbolic links.
-
.touch(list, noop: nil, verbose: nil, mtime: nil, nocreate: nil) ⇒ Object
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); returnslist
if it is an array,[list]
otherwise. -
.uptodate?(new, old_list) ⇒ Boolean
Returns
true
if the file at pathnew
is newer than all the files at paths in arrayold_list
;false
otherwise.
Instance Method Summary collapse
-
#apply_mask(mode, user_mask, op, mode_mask) ⇒ Object
:nodoc:.
-
#fu_get_gid(group) ⇒ Object
:nodoc:.
-
#fu_get_uid(user) ⇒ Object
:nodoc:.
-
#fu_have_symlink? ⇒ Boolean
:nodoc:.
-
#fu_mkdir(path, mode) ⇒ Object
:nodoc:.
-
#fu_mode(mode, path) ⇒ Object
:nodoc:.
-
#fu_stat_identical_entry?(a, b) ⇒ Boolean
:nodoc:.
-
#mode_to_s(mode) ⇒ Object
:nodoc:.
-
#remove_trailing_slash(dir) ⇒ Object
:nodoc:.
-
#symbolic_modes_to_i(mode_sym, path) ⇒ Object
:nodoc:.
-
#user_mask(target) ⇒ Object
:nodoc:.
Class Method Details
.cd(dir, verbose: nil, &block) ⇒ Object
Changes the working directory to the given dir
, which should be interpretable as a path:
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.
239 240 241 242 243 244 |
# File 'lib/fileutils.rb', line 239 def cd(dir, verbose: nil, &block) # :yield: dir "cd #{dir}" if verbose result = Dir.chdir(dir, &block) 'cd -' if verbose and block result end |
.chdir ⇒ Object
Changes the working directory to the given dir
, which should be interpretable as a path:
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.
247 248 249 250 251 252 |
# File 'lib/fileutils.rb', line 247 def cd(dir, verbose: nil, &block) # :yield: dir "cd #{dir}" if verbose result = Dir.chdir(dir, &block) 'cd -' if verbose and block result end |
.chmod(mode, list, noop: nil, verbose: nil) ⇒ Object
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.
-
Modifies each entry that is a symbolic link using File.lchmod.
Argument list
or its elements should be interpretable as paths.
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; returnsnil
. -
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.
1804 1805 1806 1807 1808 1809 1810 1811 |
# File 'lib/fileutils.rb', line 1804 def chmod(mode, list, noop: nil, verbose: nil) list = fu_list(list) sprintf('chmod %s %s', mode_to_s(mode), list.join(' ')) if verbose return if noop list.each do |path| Entry_.new(path).chmod(fu_mode(mode, path)) end end |
.chmod_R(mode, list, noop: nil, verbose: nil, force: nil) ⇒ Object
Like FileUtils.chmod, but changes permissions recursively.
1816 1817 1818 1819 1820 1821 1822 1823 1824 1825 1826 1827 1828 1829 1830 1831 |
# File 'lib/fileutils.rb', line 1816 def chmod_R(mode, list, noop: nil, verbose: nil, force: nil) list = fu_list(list) sprintf('chmod -R%s %s %s', (force ? 'f' : ''), mode_to_s(mode), list.join(' ')) if verbose return if noop list.each do |root| Entry_.new(root).traverse do |ent| begin ent.chmod(fu_mode(mode, ent.path)) rescue raise unless force end end end end |
.chown(user, group, list, noop: nil, verbose: nil) ⇒ Object
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.
-
Modifies each entry that is a symbolic link using File.lchown.
Argument list
or its elements should be interpretable as paths.
User and group:
-
Argument
user
may be a user name or a user id; ifnil
or-1
, the user is not changed. -
Argument
group
may be a group name or a group id; ifnil
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; returnsnil
. -
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.
1897 1898 1899 1900 1901 1902 1903 1904 1905 1906 1907 1908 |
# File 'lib/fileutils.rb', line 1897 def chown(user, group, list, noop: nil, verbose: nil) list = fu_list(list) sprintf('chown %s %s', (group ? "#{user}:#{group}" : user || ':'), list.join(' ')) if verbose return if noop uid = fu_get_uid(user) gid = fu_get_gid(group) list.each do |path| Entry_.new(path).chown uid, gid end end |
.chown_R(user, group, list, noop: nil, verbose: nil, force: nil) ⇒ Object
Like FileUtils.chown, but changes owner and group recursively.
1913 1914 1915 1916 1917 1918 1919 1920 1921 1922 1923 1924 1925 1926 1927 1928 1929 1930 1931 |
# File 'lib/fileutils.rb', line 1913 def chown_R(user, group, list, noop: nil, verbose: nil, force: nil) list = fu_list(list) sprintf('chown -R%s %s %s', (force ? 'f' : ''), (group ? "#{user}:#{group}" : user || ':'), list.join(' ')) if verbose return if noop uid = fu_get_uid(user) gid = fu_get_gid(group) list.each do |root| Entry_.new(root).traverse do |ent| begin ent.chown uid, gid rescue raise unless force end end end end |
.cmp ⇒ Object
Returns true
if the contents of files a
and b
are identical, false
otherwise.
Arguments a
and b
should be interpretable as a path.
FileUtils.identical? and FileUtils.cmp are aliases for FileUtils.compare_file.
Related: FileUtils.compare_stream.
1519 1520 1521 1522 1523 1524 1525 1526 |
# File 'lib/fileutils.rb', line 1519 def compare_file(a, b) return false unless File.size(a) == File.size(b) File.open(a, 'rb') {|fa| File.open(b, 'rb') {|fb| return compare_stream(fa, fb) } } end |
.collect_method(opt) ⇒ Object
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"]
2611 2612 2613 |
# File 'lib/fileutils.rb', line 2611 def self.collect_method(opt) OPT_TABLE.keys.select {|m| OPT_TABLE[m].include?(opt) } end |
.commands ⇒ Object
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"]
2572 2573 2574 |
# File 'lib/fileutils.rb', line 2572 def self.commands OPT_TABLE.keys end |
.compare_file(a, b) ⇒ Object
Returns true
if the contents of files a
and b
are identical, false
otherwise.
Arguments a
and b
should be interpretable as a path.
FileUtils.identical? and FileUtils.cmp are aliases for FileUtils.compare_file.
Related: FileUtils.compare_stream.
1508 1509 1510 1511 1512 1513 1514 1515 |
# File 'lib/fileutils.rb', line 1508 def compare_file(a, b) return false unless File.size(a) == File.size(b) File.open(a, 'rb') {|fa| File.open(b, 'rb') {|fb| return compare_stream(fa, fb) } } end |
.compare_stream(a, b) ⇒ Object
Returns true
if the contents of streams a
and b
are identical, false
otherwise.
Arguments a
and b
should be interpretable as a path.
Related: FileUtils.compare_file.
1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 |
# File 'lib/fileutils.rb', line 1531 def compare_stream(a, b) bsize = fu_stream_blksize(a, b) sa = String.new(capacity: bsize) sb = String.new(capacity: bsize) begin a.read(bsize, sa) b.read(bsize, sb) return true if sa.empty? && sb.empty? end while sa == sb false end |
.copy ⇒ Object
Copies files.
Arguments src
(a single path or an array of paths) and dest
(a single path) should be interpretable as paths.
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.
883 884 885 886 887 888 889 |
# File 'lib/fileutils.rb', line 883 def cp(src, dest, preserve: nil, noop: nil, verbose: nil) "cp#{preserve ? ' -p' : ''} #{[src,dest].flatten.join ' '}" if verbose return if noop fu_each_src_dest(src, dest) do |s, d| copy_file s, d, preserve end end |
.copy_entry(src, dest, preserve = false, dereference_root = false, remove_destination = false) ⇒ Object
Recursively copies files from src
to dest
.
Arguments src
and dest
should be interpretable as paths.
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
- ifsrc
is a symbolic link, follows the link. -
preserve: true
- preserves file times. -
remove_destination: true
- removesdest
before copying files.
Related: methods for copying.
1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 |
# File 'lib/fileutils.rb', line 1041 def copy_entry(src, dest, preserve = false, dereference_root = false, remove_destination = false) if dereference_root src = File.realpath(src) end Entry_.new(src, nil, false).wrap_traverse(proc do |ent| destent = Entry_.new(dest, ent.rel, false) File.unlink destent.path if remove_destination && (File.file?(destent.path) || File.symlink?(destent.path)) ent.copy destent.path end, proc do |ent| destent = Entry_.new(dest, ent.rel, false) ent. destent.path if preserve end) end |
.copy_file(src, dest, preserve = false, dereference = true) ⇒ Object
Copies file from src
to dest
, which should not be directories.
Arguments src
and dest
should be interpretable as paths.
Examples:
FileUtils.touch('src0.txt')
FileUtils.copy_file('src0.txt', 'dest0.txt')
File.file?('dest0.txt') # => true
Keyword arguments:
-
dereference: false
- ifsrc
is a symbolic link, does not follow the link. -
preserve: true
- preserves file times. -
remove_destination: true
- removesdest
before copying files.
Related: methods for copying.
1077 1078 1079 1080 1081 |
# File 'lib/fileutils.rb', line 1077 def copy_file(src, dest, preserve = false, dereference = true) ent = Entry_.new(src, nil, dereference) ent.copy_file dest ent. dest if preserve end |
.copy_stream(src, dest) ⇒ Object
Copies IO stream src
to IO stream dest
via IO.copy_stream.
Related: methods for copying.
1089 1090 1091 |
# File 'lib/fileutils.rb', line 1089 def copy_stream(src, dest) IO.copy_stream(src, dest) end |
.cp(src, dest, preserve: nil, noop: nil, verbose: nil) ⇒ Object
Copies files.
Arguments src
(a single path or an array of paths) and dest
(a single path) should be interpretable as paths.
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.
874 875 876 877 878 879 880 |
# File 'lib/fileutils.rb', line 874 def cp(src, dest, preserve: nil, noop: nil, verbose: nil) "cp#{preserve ? ' -p' : ''} #{[src,dest].flatten.join ' '}" if verbose return if noop fu_each_src_dest(src, dest) do |s, d| copy_file s, d, preserve end end |
.cp_lr(src, dest, noop: nil, verbose: nil, dereference_root: true, remove_destination: false) ⇒ Object
Creates hard links.
Arguments src
(a single path or an array of paths) and dest
(a single path) should be interpretable as paths.
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
- ifsrc
is a symbolic link, does not dereference it. -
noop: true
- does not create links. -
remove_destination: true
- removesdest
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.
628 629 630 631 632 633 634 635 |
# File 'lib/fileutils.rb', line 628 def cp_lr(src, dest, noop: nil, verbose: nil, dereference_root: true, remove_destination: false) "cp -lr#{remove_destination ? ' --remove-destination' : ''} #{[src,dest].flatten.join ' '}" if verbose return if noop fu_each_src_dest(src, dest) do |s, d| link_entry s, d, dereference_root, remove_destination end end |
.cp_r(src, dest, preserve: nil, noop: nil, verbose: nil, dereference_root: true, remove_destination: nil) ⇒ Object
Recursively copies files.
Arguments src
(a single path or an array of paths) and dest
(a single path) should be interpretable as paths.
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
- ifsrc
is a symbolic link, does not dereference it. -
noop: true
- does not copy files. -
preserve: true
- preserves file times. -
remove_destination: true
- removesdest
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.
986 987 988 989 990 991 992 993 |
# File 'lib/fileutils.rb', line 986 def cp_r(src, dest, preserve: nil, noop: nil, verbose: nil, dereference_root: true, remove_destination: nil) "cp -r#{preserve ? 'p' : ''}#{remove_destination ? ' --remove-destination' : ''} #{[src,dest].flatten.join ' '}" if verbose return if noop fu_each_src_dest(src, dest) do |s, d| copy_entry s, d, preserve, dereference_root, remove_destination end end |
.getwd ⇒ Object
203 204 205 |
# File 'lib/fileutils.rb', line 203 def pwd Dir.pwd end |
.have_option?(mid, opt) ⇒ Boolean
2590 2591 2592 2593 |
# File 'lib/fileutils.rb', line 2590 def self.have_option?(mid, opt) li = OPT_TABLE[mid.to_s] or raise ArgumentError, "no such method: #{mid}" li.include?(opt) end |
.identical? ⇒ Object
Returns true
if the contents of files a
and b
are identical, false
otherwise.
Arguments a
and b
should be interpretable as a path.
FileUtils.identical? and FileUtils.cmp are aliases for FileUtils.compare_file.
Related: FileUtils.compare_stream.
1518 1519 1520 1521 1522 1523 1524 1525 |
# File 'lib/fileutils.rb', line 1518 def compare_file(a, b) return false unless File.size(a) == File.size(b) File.open(a, 'rb') {|fa| File.open(b, 'rb') {|fb| return compare_stream(fa, fb) } } end |
.install(src, dest, mode: nil, owner: nil, group: nil, preserve: nil, noop: nil, verbose: nil) ⇒ Object
Copies a file entry. See install(1).
Arguments src
(a single path or an array of paths) and dest
(a single path) should be interpretable as paths;
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 notnil
, using File.chown. -
mode: permissions
- changes the permissions. using File.chmod. -
noop: true
- does not copy entries; returnsnil
. -
owner: owner
- changes the owner if notnil
, using File.chown. -
preserve: true
- preserve timestamps using 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.
1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 |
# File 'lib/fileutils.rb', line 1610 def install(src, dest, mode: nil, owner: nil, group: nil, preserve: nil, noop: nil, verbose: nil) if verbose msg = +"install -c" msg << ' -p' if preserve msg << ' -m ' << mode_to_s(mode) if mode msg << " -o #{owner}" if owner msg << " -g #{group}" if group msg << ' ' << [src,dest].flatten.join(' ') msg end return if noop uid = fu_get_uid(owner) gid = fu_get_gid(group) fu_each_src_dest(src, dest) do |s, d| st = File.stat(s) unless File.exist?(d) and compare_file(s, d) remove_file d, true if d.end_with?('/') mkdir_p d copy_file s, d + File.basename(s) else mkdir_p File.('..', d) copy_file s, d end File.utime st.atime, st.mtime, d if preserve File.chmod fu_mode(mode, st), d if mode File.chown uid, gid, d if uid or gid end end end |
.link ⇒ Object
Creates hard links.
Arguments src
(a single path or an array of paths) and dest
(a single path) should be interpretable as paths.
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
- overwritesdest
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).
527 528 529 530 531 532 533 534 |
# File 'lib/fileutils.rb', line 527 def ln(src, dest, force: nil, noop: nil, verbose: nil) "ln#{force ? ' -f' : ''} #{[src,dest].flatten.join ' '}" if verbose return if noop fu_each_src_dest0(src, dest) do |s,d| remove_file d, true if force File.link s, d end end |
.link_entry(src, dest, dereference_root = false, remove_destination = false) ⇒ Object
Creates hard links; returns nil
.
Arguments src
and dest
should be interpretable as paths.
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
- dereferencessrc
if it is a symbolic link. -
remove_destination: true
- removesdest
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).
813 814 815 816 817 818 819 |
# File 'lib/fileutils.rb', line 813 def link_entry(src, dest, dereference_root = false, remove_destination = false) Entry_.new(src, nil, dereference_root).traverse do |ent| destent = Entry_.new(dest, ent.rel, false) File.unlink destent.path if remove_destination && File.file?(destent.path) ent.link destent.path end end |
.ln(src, dest, force: nil, noop: nil, verbose: nil) ⇒ Object
Creates hard links.
Arguments src
(a single path or an array of paths) and dest
(a single path) should be interpretable as paths.
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
- overwritesdest
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).
517 518 519 520 521 522 523 524 |
# File 'lib/fileutils.rb', line 517 def ln(src, dest, force: nil, noop: nil, verbose: nil) "ln#{force ? ' -f' : ''} #{[src,dest].flatten.join ' '}" if verbose return if noop fu_each_src_dest0(src, dest) do |s,d| remove_file d, true if force File.link s, d end end |
.ln_s(src, dest, force: nil, relative: false, target_directory: true, noop: nil, verbose: nil) ⇒ Object
Creates symbolic links.
Arguments src
(a single path or an array of paths) and dest
(a single path) should be interpretable as paths.
If src
is the path to an existing file:
-
When
dest
is the path to a non-existent file, creates a symbolic link atdest
pointing tosrc
: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 atdest
pointing tosrc
if and only if keyword argumentforce: 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
- overwritesdest
if it exists. -
relative: false
- create links relative todest
. -
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.
707 708 709 710 711 712 713 714 715 716 717 |
# File 'lib/fileutils.rb', line 707 def ln_s(src, dest, force: nil, relative: false, target_directory: true, noop: nil, verbose: nil) if relative return ln_sr(src, dest, force: force, noop: noop, verbose: verbose) end "ln -s#{force ? 'f' : ''} #{[src,dest].flatten.join ' '}" if verbose return if noop fu_each_src_dest0(src, dest) do |s,d| remove_file d, true if force File.symlink s, d end end |
.ln_sf(src, dest, noop: nil, verbose: nil) ⇒ Object
Like FileUtils.ln_s, but always with keyword argument force: true
given.
725 726 727 |
# File 'lib/fileutils.rb', line 725 def ln_sf(src, dest, noop: nil, verbose: nil) ln_s src, dest, force: true, noop: noop, verbose: verbose end |
.ln_sr(src, dest, target_directory: true, force: nil, noop: nil, verbose: nil) ⇒ Object
Like FileUtils.ln_s, but create links relative to dest
.
732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 |
# File 'lib/fileutils.rb', line 732 def ln_sr(src, dest, target_directory: true, force: nil, noop: nil, verbose: nil) = "#{force ? 'f' : ''}#{target_directory ? '' : 'T'}" dest = File.path(dest) srcs = Array(src) link = proc do |s, target_dir_p = true| s = File.path(s) if target_dir_p d = File.join(destdirs = dest, File.basename(s)) else destdirs = File.dirname(d = dest) end destdirs = fu_split_path(File.realpath(destdirs)) if fu_starting_path?(s) srcdirs = fu_split_path((File.realdirpath(s) rescue File.(s))) base = fu_relative_components_from(srcdirs, destdirs) s = File.join(*base) else srcdirs = fu_clean_components(*fu_split_path(s)) base = fu_relative_components_from(fu_split_path(Dir.pwd), destdirs) while srcdirs.first&. == ".." and base.last&.!=("..") and !fu_starting_path?(base.last) srcdirs.shift base.pop end s = File.join(*base, *srcdirs) end "ln -s#{} #{s} #{d}" if verbose next if noop remove_file d, true if force File.symlink s, d end case srcs.size when 0 when 1 link[srcs[0], target_directory && File.directory?(dest)] else srcs.each(&link) end end |
.makedirs ⇒ Object
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.
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:
FileUtils.mkdir_p(%w[tmp0/tmp1 tmp2/tmp3]) # => ["tmp0/tmp1", "tmp2/tmp3"]
FileUtils.mkdir_p('tmp4/tmp5') # => ["tmp4/tmp5"]
Keyword arguments:
-
mode: mode
- also callsFile.chmod(mode, path)
; see 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.
393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 |
# File 'lib/fileutils.rb', line 393 def mkdir_p(list, mode: nil, noop: nil, verbose: nil) list = fu_list(list) "mkdir -p #{mode ? ('-m %03o ' % mode) : ''}#{list.join ' '}" if verbose return *list if noop list.each do |item| path = remove_trailing_slash(item) stack = [] until File.directory?(path) || File.dirname(path) == path stack.push path path = File.dirname(path) end stack.reverse_each do |dir| begin fu_mkdir dir, mode rescue SystemCallError raise unless File.directory?(dir) end end end return *list end |
.mkdir(list, mode: nil, noop: nil, verbose: nil) ⇒ Object
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.
With no keyword arguments, creates a directory at each path
in list
by calling: Dir.mkdir(path, mode)
; see Dir.mkdir:
FileUtils.mkdir(%w[tmp0 tmp1]) # => ["tmp0", "tmp1"]
FileUtils.mkdir('tmp4') # => ["tmp4"]
Keyword arguments:
-
mode: mode
- also callsFile.chmod(mode, path)
; see 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.
317 318 319 320 321 322 323 324 325 |
# File 'lib/fileutils.rb', line 317 def mkdir(list, mode: nil, noop: nil, verbose: nil) list = fu_list(list) "mkdir #{mode ? ('-m %03o ' % mode) : ''}#{list.join ' '}" if verbose return if noop list.each do |dir| fu_mkdir dir, mode end end |
.mkdir_p(list, mode: nil, noop: nil, verbose: nil) ⇒ Object
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.
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:
FileUtils.mkdir_p(%w[tmp0/tmp1 tmp2/tmp3]) # => ["tmp0/tmp1", "tmp2/tmp3"]
FileUtils.mkdir_p('tmp4/tmp5') # => ["tmp4/tmp5"]
Keyword arguments:
-
mode: mode
- also callsFile.chmod(mode, path)
; see 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.
366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 |
# File 'lib/fileutils.rb', line 366 def mkdir_p(list, mode: nil, noop: nil, verbose: nil) list = fu_list(list) "mkdir -p #{mode ? ('-m %03o ' % mode) : ''}#{list.join ' '}" if verbose return *list if noop list.each do |item| path = remove_trailing_slash(item) stack = [] until File.directory?(path) || File.dirname(path) == path stack.push path path = File.dirname(path) end stack.reverse_each do |dir| begin fu_mkdir dir, mode rescue SystemCallError raise unless File.directory?(dir) end end end return *list end |
.mkpath ⇒ Object
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.
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:
FileUtils.mkdir_p(%w[tmp0/tmp1 tmp2/tmp3]) # => ["tmp0/tmp1", "tmp2/tmp3"]
FileUtils.mkdir_p('tmp4/tmp5') # => ["tmp4/tmp5"]
Keyword arguments:
-
mode: mode
- also callsFile.chmod(mode, path)
; see 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.
392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 |
# File 'lib/fileutils.rb', line 392 def mkdir_p(list, mode: nil, noop: nil, verbose: nil) list = fu_list(list) "mkdir -p #{mode ? ('-m %03o ' % mode) : ''}#{list.join ' '}" if verbose return *list if noop list.each do |item| path = remove_trailing_slash(item) stack = [] until File.directory?(path) || File.dirname(path) == path stack.push path path = File.dirname(path) end stack.reverse_each do |dir| begin fu_mkdir dir, mode rescue SystemCallError raise unless File.directory?(dir) end end end return *list end |
.move ⇒ Object
Moves entries.
Arguments src
(a single path or an array of paths) and dest
(a single path) should be interpretable as paths.
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.
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 removingsrc
(that is, ifsrc
anddest
are on different file systems), ignores raised exceptions of StandardError and its descendants. -
noop: true
- does not move files. -
secure: true
- removessrc
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
1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 |
# File 'lib/fileutils.rb', line 1187 def mv(src, dest, force: nil, noop: nil, verbose: nil, secure: nil) "mv#{force ? ' -f' : ''} #{[src,dest].flatten.join ' '}" if verbose return if noop fu_each_src_dest(src, dest) do |s, d| destent = Entry_.new(d, nil, true) begin if destent.exist? if destent.directory? raise Errno::EEXIST, d end end begin File.rename s, d rescue Errno::EXDEV, Errno::EPERM # move from unencrypted to encrypted dir (ext4) copy_entry s, d, true if secure remove_entry_secure s, force else remove_entry s, force end end rescue SystemCallError raise unless force end end end |
.mv(src, dest, force: nil, noop: nil, verbose: nil, secure: nil) ⇒ Object
Moves entries.
Arguments src
(a single path or an array of paths) and dest
(a single path) should be interpretable as paths.
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.
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 removingsrc
(that is, ifsrc
anddest
are on different file systems), ignores raised exceptions of StandardError and its descendants. -
noop: true
- does not move files. -
secure: true
- removessrc
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
1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 |
# File 'lib/fileutils.rb', line 1158 def mv(src, dest, force: nil, noop: nil, verbose: nil, secure: nil) "mv#{force ? ' -f' : ''} #{[src,dest].flatten.join ' '}" if verbose return if noop fu_each_src_dest(src, dest) do |s, d| destent = Entry_.new(d, nil, true) begin if destent.exist? if destent.directory? raise Errno::EEXIST, d end end begin File.rename s, d rescue Errno::EXDEV, Errno::EPERM # move from unencrypted to encrypted dir (ext4) copy_entry s, d, true if secure remove_entry_secure s, force else remove_entry s, force end end rescue SystemCallError raise unless force end end end |
.options ⇒ Object
Returns an array of the string keyword names:
FileUtils..take(3) # => ["noop", "verbose", "force"]
2580 2581 2582 |
# File 'lib/fileutils.rb', line 2580 def self. OPT_TABLE.values.flatten.uniq.map {|sym| sym.to_s } end |
.options_of(mid) ⇒ Object
2601 2602 2603 |
# File 'lib/fileutils.rb', line 2601 def self.(mid) OPT_TABLE[mid.to_s].map {|sym| sym.to_s } end |
.private_module_function(name) ⇒ Object
:nodoc:
186 187 188 189 |
# File 'lib/fileutils.rb', line 186 def self.private_module_function(name) #:nodoc: module_function name private_class_method name end |
.pwd ⇒ Object
Returns a string containing the path to the current directory:
FileUtils.pwd # => "/rdoc/fileutils"
Related: FileUtils.cd.
198 199 200 |
# File 'lib/fileutils.rb', line 198 def pwd Dir.pwd end |
.remove ⇒ Object
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.
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; returnsnil
. -
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.
1228 1229 1230 1231 1232 1233 1234 1235 1236 |
# File 'lib/fileutils.rb', line 1228 def rm(list, force: nil, noop: nil, verbose: nil) list = fu_list(list) "rm#{force ? ' -f' : ''} #{list.join ' '}" if verbose return if noop list.each do |path| remove_file path, force end end |
.remove_dir(path, force = false) ⇒ Object
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.
Optional argument force
specifies whether to ignore raised exceptions of StandardError and its descendants.
Related: methods for deleting.
1493 1494 1495 |
# File 'lib/fileutils.rb', line 1493 def remove_dir(path, force = false) remove_entry path, force # FIXME?? check if it is a directory end |
.remove_entry(path, force = false) ⇒ Object
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.
Optional argument force
specifies whether to ignore raised exceptions of StandardError and its descendants.
Related: FileUtils.remove_entry_secure.
1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 |
# File 'lib/fileutils.rb', line 1450 def remove_entry(path, force = false) Entry_.new(path).postorder_traverse do |ent| begin ent.remove rescue raise unless force end end rescue raise unless force end |
.remove_entry_secure(path, force = false) ⇒ Object
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.
Avoids a local vulnerability that can exist in certain circumstances; see Avoiding the TOCTTOU Vulnerability.
Optional argument force
specifies whether to ignore raised exceptions of StandardError and its descendants.
Related: methods for deleting.
1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 |
# File 'lib/fileutils.rb', line 1352 def remove_entry_secure(path, force = false) unless fu_have_symlink? remove_entry path, force return end fullpath = File.(path) st = File.lstat(fullpath) unless st.directory? File.unlink fullpath return end # is a directory. parent_st = File.stat(File.dirname(fullpath)) unless parent_st.world_writable? remove_entry path, force return end unless parent_st.sticky? raise ArgumentError, "parent directory is world writable, FileUtils#remove_entry_secure does not work; abort: #{path.inspect} (parent directory mode #{'%o' % parent_st.mode})" end # freeze tree root euid = Process.euid dot_file = fullpath + "/." begin File.open(dot_file) {|f| unless fu_stat_identical_entry?(st, f.stat) # symlink (TOC-to-TOU attack?) File.unlink fullpath return end f.chown euid, -1 f.chmod 0700 } rescue Errno::EISDIR # JRuby in non-native mode can't open files as dirs File.lstat(dot_file).tap {|fstat| unless fu_stat_identical_entry?(st, fstat) # symlink (TOC-to-TOU attack?) File.unlink fullpath return end File.chown euid, -1, dot_file File.chmod 0700, dot_file } end unless fu_stat_identical_entry?(st, File.lstat(fullpath)) # TOC-to-TOU attack? File.unlink fullpath return end # ---- tree root is frozen ---- root = Entry_.new(path) root.preorder_traverse do |ent| if ent.directory? ent.chown euid, -1 ent.chmod 0700 end end root.postorder_traverse do |ent| begin ent.remove rescue raise unless force end end rescue raise unless force end |
.remove_file(path, force = false) ⇒ Object
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.
Optional argument force
specifies whether to ignore raised exceptions of StandardError and its descendants.
Related: methods for deleting.
1474 1475 1476 1477 1478 |
# File 'lib/fileutils.rb', line 1474 def remove_file(path, force = false) Entry_.new(path).remove_file rescue raise unless force end |
.rm(list, force: nil, noop: nil, verbose: nil) ⇒ Object
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.
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; returnsnil
. -
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.
1217 1218 1219 1220 1221 1222 1223 1224 1225 |
# File 'lib/fileutils.rb', line 1217 def rm(list, force: nil, noop: nil, verbose: nil) list = fu_list(list) "rm#{force ? ' -f' : ''} #{list.join ' '}" if verbose return if noop list.each do |path| remove_file path, force end end |
.rm_f(list, noop: nil, verbose: nil) ⇒ Object
Equivalent to:
FileUtils.rm(list, force: true, **kwargs)
Argument list
(a single path or an array of paths) should be interpretable as paths.
See FileUtils.rm for keyword arguments.
Related: methods for deleting.
1242 1243 1244 |
# File 'lib/fileutils.rb', line 1242 def rm_f(list, noop: nil, verbose: nil) rm list, force: true, noop: noop, verbose: verbose end |
.rm_r(list, force: nil, noop: nil, verbose: nil, secure: nil) ⇒ Object
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.
May cause a local vulnerability if not called with keyword argument secure: true
; see 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; returnsnil
. -
secure: true
- removessrc
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.
1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 |
# File 'lib/fileutils.rb', line 1300 def rm_r(list, force: nil, noop: nil, verbose: nil, secure: nil) list = fu_list(list) "rm -r#{force ? 'f' : ''} #{list.join ' '}" if verbose return if noop list.each do |path| if secure remove_entry_secure path, force else remove_entry path, force end end end |
.rm_rf(list, noop: nil, verbose: nil, secure: nil) ⇒ Object
Equivalent to:
FileUtils.rm_r(list, force: true, **kwargs)
Argument list
or its elements should be interpretable as paths.
May cause a local vulnerability if not called with keyword argument secure: true
; see Avoiding the TOCTTOU Vulnerability.
See FileUtils.rm_r for keyword arguments.
Related: methods for deleting.
1329 1330 1331 |
# File 'lib/fileutils.rb', line 1329 def rm_rf(list, noop: nil, verbose: nil, secure: nil) rm_r list, force: true, noop: noop, verbose: verbose, secure: secure end |
.rmdir(list, parents: nil, noop: nil, verbose: nil) ⇒ Object
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.
With no keyword arguments, removes the directory at each path
in list
, by calling: Dir.rmdir(path)
; see 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.
443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 |
# File 'lib/fileutils.rb', line 443 def rmdir(list, parents: nil, noop: nil, verbose: nil) list = fu_list(list) "rmdir #{parents ? '-p ' : ''}#{list.join ' '}" if verbose return if noop list.each do |dir| Dir.rmdir(dir = remove_trailing_slash(dir)) if parents begin until (parent = File.dirname(dir)) == '.' or parent == dir dir = parent Dir.rmdir(dir) end rescue Errno::ENOTEMPTY, Errno::EEXIST, Errno::ENOENT end end end end |
.rmtree ⇒ Object
Equivalent to:
FileUtils.rm_r(list, force: true, **kwargs)
Argument list
or its elements should be interpretable as paths.
May cause a local vulnerability if not called with keyword argument secure: true
; see Avoiding the TOCTTOU Vulnerability.
See FileUtils.rm_r for keyword arguments.
Related: methods for deleting.
1334 1335 1336 |
# File 'lib/fileutils.rb', line 1334 def rm_rf(list, noop: nil, verbose: nil, secure: nil) rm_r list, force: true, noop: noop, verbose: verbose, secure: secure end |
.safe_unlink ⇒ Object
Equivalent to:
FileUtils.rm(list, force: true, **kwargs)
Argument list
(a single path or an array of paths) should be interpretable as paths.
See FileUtils.rm for keyword arguments.
Related: methods for deleting.
1247 1248 1249 |
# File 'lib/fileutils.rb', line 1247 def rm_f(list, noop: nil, verbose: nil) rm list, force: true, noop: noop, verbose: verbose end |
.symlink ⇒ Object
Creates symbolic links.
Arguments src
(a single path or an array of paths) and dest
(a single path) should be interpretable as paths.
If src
is the path to an existing file:
-
When
dest
is the path to a non-existent file, creates a symbolic link atdest
pointing tosrc
: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 atdest
pointing tosrc
if and only if keyword argumentforce: 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
- overwritesdest
if it exists. -
relative: false
- create links relative todest
. -
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.
720 721 722 723 724 725 726 727 728 729 730 |
# File 'lib/fileutils.rb', line 720 def ln_s(src, dest, force: nil, relative: false, target_directory: true, noop: nil, verbose: nil) if relative return ln_sr(src, dest, force: force, noop: noop, verbose: verbose) end "ln -s#{force ? 'f' : ''} #{[src,dest].flatten.join ' '}" if verbose return if noop fu_each_src_dest0(src, dest) do |s,d| remove_file d, true if force File.symlink s, d end end |
.touch(list, noop: nil, verbose: nil, mtime: nil, nocreate: nil) ⇒ Object
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.
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; returnsnil
. -
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?.
2007 2008 2009 2010 2011 2012 2013 2014 2015 2016 2017 2018 2019 2020 2021 2022 2023 2024 2025 2026 2027 |
# File 'lib/fileutils.rb', line 2007 def touch(list, noop: nil, verbose: nil, mtime: nil, nocreate: nil) list = fu_list(list) t = mtime if verbose "touch #{nocreate ? '-c ' : ''}#{t ? t.strftime('-t %Y%m%d%H%M.%S ') : ''}#{list.join ' '}" end return if noop list.each do |path| created = nocreate begin File.utime(t, t, path) rescue Errno::ENOENT raise if created File.open(path, 'a') { ; } created = true retry if t end end end |
.uptodate?(new, old_list) ⇒ Boolean
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:
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.
265 266 267 268 269 270 271 272 273 274 |
# File 'lib/fileutils.rb', line 265 def uptodate?(new, old_list) return false unless File.exist?(new) new_time = File.mtime(new) old_list.each do |old| if File.exist?(old) return false unless new_time > File.mtime(old) end end true end |
Instance Method Details
#apply_mask(mode, user_mask, op, mode_mask) ⇒ Object
:nodoc:
1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 |
# File 'lib/fileutils.rb', line 1661 def apply_mask(mode, user_mask, op, mode_mask) #:nodoc: case op when '=' (mode & ~user_mask) | (user_mask & mode_mask) when '+' mode | (user_mask & mode_mask) when '-' mode & ~(user_mask & mode_mask) end end |
#fu_get_gid(group) ⇒ Object
:nodoc:
1948 1949 1950 1951 1952 1953 1954 1955 1956 1957 1958 1959 |
# File 'lib/fileutils.rb', line 1948 def fu_get_gid(group) #:nodoc: return nil unless group case group when Integer group when /\A\d+\z/ group.to_i else require 'etc' Etc.getgrnam(group) ? Etc.getgrnam(group).gid : nil end end |
#fu_get_uid(user) ⇒ Object
:nodoc:
1934 1935 1936 1937 1938 1939 1940 1941 1942 1943 1944 1945 |
# File 'lib/fileutils.rb', line 1934 def fu_get_uid(user) #:nodoc: return nil unless user case user when Integer user when /\A\d+\z/ user.to_i else require 'etc' Etc.getpwnam(user) ? Etc.getpwnam(user).uid : nil end end |
#fu_have_symlink? ⇒ Boolean
:nodoc:
1424 1425 1426 1427 1428 1429 1430 |
# File 'lib/fileutils.rb', line 1424 def fu_have_symlink? #:nodoc: File.symlink nil, nil rescue NotImplementedError return false rescue TypeError return true end |
#fu_mkdir(path, mode) ⇒ Object
:nodoc:
397 398 399 400 401 402 403 404 405 |
# File 'lib/fileutils.rb', line 397 def fu_mkdir(path, mode) #:nodoc: path = remove_trailing_slash(path) if mode Dir.mkdir path, mode File.chmod mode, path else Dir.mkdir path end end |
#fu_mode(mode, path) ⇒ Object
:nodoc:
1722 1723 1724 |
# File 'lib/fileutils.rb', line 1722 def fu_mode(mode, path) #:nodoc: mode.is_a?(String) ? symbolic_modes_to_i(mode, path) : mode end |
#fu_stat_identical_entry?(a, b) ⇒ Boolean
:nodoc:
1433 1434 1435 |
# File 'lib/fileutils.rb', line 1433 def fu_stat_identical_entry?(a, b) #:nodoc: a.dev == b.dev and a.ino == b.ino end |
#mode_to_s(mode) ⇒ Object
:nodoc:
1727 1728 1729 |
# File 'lib/fileutils.rb', line 1727 def mode_to_s(mode) #:nodoc: mode.is_a?(String) ? mode : "%o" % mode end |
#remove_trailing_slash(dir) ⇒ Object
:nodoc:
277 278 279 |
# File 'lib/fileutils.rb', line 277 def remove_trailing_slash(dir) #:nodoc: dir == '/' ? dir : dir.chomp(?/) end |
#symbolic_modes_to_i(mode_sym, path) ⇒ Object
:nodoc:
1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 |
# File 'lib/fileutils.rb', line 1673 def symbolic_modes_to_i(mode_sym, path) #:nodoc: path = File.stat(path) unless File::Stat === path mode = path.mode mode_sym.split(/,/).inject(mode & 07777) do |current_mode, clause| target, *actions = clause.split(/([=+-])/) raise ArgumentError, "invalid file mode: #{mode_sym}" if actions.empty? target = 'a' if target.empty? user_mask = user_mask(target) actions.each_slice(2) do |op, perm| need_apply = op == '=' mode_mask = (perm || '').each_char.inject(0) do |mask, chr| case chr when "r" mask | 0444 when "w" mask | 0222 when "x" mask | 0111 when "X" if path.directory? mask | 0111 else mask end when "s" mask | 06000 when "t" mask | 01000 when "u", "g", "o" if mask.nonzero? current_mode = apply_mask(current_mode, user_mask, op, mask) end need_apply = false copy_mask = user_mask(chr) (current_mode & copy_mask) / (copy_mask & 0111) * (user_mask & 0111) else raise ArgumentError, "invalid 'perm' symbol in file mode: #{chr}" end end if mode_mask.nonzero? || need_apply current_mode = apply_mask(current_mode, user_mask, op, mode_mask) end end current_mode end end |
#user_mask(target) ⇒ Object
:nodoc:
1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 |
# File 'lib/fileutils.rb', line 1643 def user_mask(target) #:nodoc: target.each_char.inject(0) do |mask, chr| case chr when "u" mask | 04700 when "g" mask | 02070 when "o" mask | 01007 when "a" mask | 07777 else raise ArgumentError, "invalid 'who' symbol in file mode: #{chr}" end end end |