module FileUtils
Namespace for file utility methods for copying, moving, removing, etc.
What’s Here¶↑
First, what’s elsewhere. Module FileUtils:
Inherits fromclass Object.
Supplementsclass 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_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_f,::safe_unlink: Like::rm, but removes forcibly.::rm_r: Removes entries and their descendants.::rmdir: Removes directories.
Querying¶↑
::uptodate?: Returns whether a given entry is newer than given other entries.
Setting¶↑
::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_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¶↑
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 acceptpath 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 thetree 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:
deftree(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 theTime-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_rwith keyword argumentsecure: true.FileUtils.rm_rfwith keyword argumentsecure: 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.mvwith keyword argumentsecure: 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#chownandFile#chmodin removing directories.The owner of the target directory should be either the current process or the super user (root).
WARNING: You must ensure thatALL 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:
Constants
- VERSION
The version number.
Public Class Methods
Source
# File lib/fileutils.rb, line 239defcd(dir,verbose:nil,&block)# :yield: dirfu_output_message"cd #{dir}"ifverboseresult =Dir.chdir(dir,&block)fu_output_message'cd -'ifverboseandblockresultend
Changes the working directory to the givendir, which should beinterpretable as a path:
With no block given, changes the current directory to the directory atdir; 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 atdir, calls the block with argumentdir, 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.
Source
# File lib/fileutils.rb, line 1801defchmod(mode,list,noop:nil,verbose:nil)list =fu_list(list)fu_output_messagesprintf('chmod %s %s',mode_to_s(mode),list.join(' '))ifverbosereturnifnooplist.eachdo|path|Entry_.new(path).chmod(fu_mode(mode,path))endend
Changes permissions on the entries at the paths given inlist (a single path or an array of paths) to the permissions given bymode; returnslist 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.
Argumentlist or its elements should beinterpretable as paths.
Argumentmode 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:targetsmay 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.
operatormay 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.txtchmod 644 src0.txt src0.datchmod u=wrx,go=rx src1.txtchmod u=wrx,go=rx /usr/bin/ruby
Related:FileUtils.chmod_R.
Source
# File lib/fileutils.rb, line 1813defchmod_R(mode,list,noop:nil,verbose:nil,force:nil)list =fu_list(list)fu_output_messagesprintf('chmod -R%s %s %s', (force?'f':''),mode_to_s(mode),list.join(' '))ifverbosereturnifnooplist.eachdo|root|Entry_.new(root).traversedo|ent|beginent.chmod(fu_mode(mode,ent.path))rescueraiseunlessforceendendendend
LikeFileUtils.chmod, but changes permissions recursively.
Source
# File lib/fileutils.rb, line 1894defchown(user,group,list,noop:nil,verbose:nil)list =fu_list(list)fu_output_messagesprintf('chown %s %s', (group?"#{user}:#{group}":user||':'),list.join(' '))ifverbosereturnifnoopuid =fu_get_uid(user)gid =fu_get_gid(group)list.eachdo|path|Entry_.new(path).chownuid,gidendend
Changes the owner and group on the entries at the paths given inlist (a single path or an array of paths) to the givenuser andgroup; returnslist 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.
Argumentlist or its elements should beinterpretable as paths.
User and group:
Argument
usermay be a user name or a user id; ifnilor-1, the user is not changed.Argument
groupmay be a group name or a group id; ifnilor-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# => 1004File.stat('src0.txt').gid# => 1004FileUtils.chown('user2','group1','src0.txt')File.stat('src0.txt').uid# => 1006File.stat('src0.txt').gid# => 1005# User and group as uid and gid.FileUtils.chown(1004,1004,'src0.txt')File.stat('src0.txt').uid# => 1004File.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.txtchown 1004:1004 src0.txtchown 1006:1005 src0.txt src0.datchown user2:group1 src0.txtchown user2:group1 .
Related:FileUtils.chown_R.
Source
# File lib/fileutils.rb, line 1910defchown_R(user,group,list,noop:nil,verbose:nil,force:nil)list =fu_list(list)fu_output_messagesprintf('chown -R%s %s %s', (force?'f':''), (group?"#{user}:#{group}":user||':'),list.join(' '))ifverbosereturnifnoopuid =fu_get_uid(user)gid =fu_get_gid(group)list.eachdo|root|Entry_.new(root).traversedo|ent|beginent.chownuid,gidrescueraiseunlessforceendendendend
LikeFileUtils.chown, but changes owner and group recursively.
Source
# File lib/fileutils.rb, line 2616defself.collect_method(opt)OPT_TABLE.keys.select {|m|OPT_TABLE[m].include?(opt) }end
Returns an array of the string method names of the methods that accept the given keyword optionopt; the argument must be a symbol:
FileUtils.collect_method(:preserve)# => ["cp", "copy", "cp_r", "install"]
Source
# File lib/fileutils.rb, line 2577defself.commandsOPT_TABLE.keysend
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"]
Source
# File lib/fileutils.rb, line 1505defcompare_file(a,b)returnfalseunlessFile.size(a)==File.size(b)File.open(a,'rb') {|fa|File.open(b,'rb') {|fb|returncompare_stream(fa,fb) } }end
Returnstrue if the contents of filesa andb are identical,false otherwise.
Argumentsa andb should beinterpretable as a path.
FileUtils.identical? andFileUtils.cmp are aliases forFileUtils.compare_file.
Related:FileUtils.compare_stream.
Source
# File lib/fileutils.rb, line 1528defcompare_stream(a,b)bsize =fu_stream_blksize(a,b)sa =String.new(capacity:bsize)sb =String.new(capacity:bsize)begina.read(bsize,sa)b.read(bsize,sb)returntrueifsa.empty?&&sb.empty?endwhilesa==sbfalseend
Returnstrue if the contents of streamsa andb are identical,false otherwise.
Argumentsa andb should beinterpretable as a path.
Related:FileUtils.compare_file.
Source
# File lib/fileutils.rb, line 1037defcopy_entry(src,dest,preserve =false,dereference_root =false,remove_destination =false)ifdereference_rootsrc =File.realpath(src)endEntry_.new(src,nil,false).wrap_traverse(procdo|ent|destent =Entry_.new(dest,ent.rel,false)File.unlinkdestent.pathifremove_destination&& (File.file?(destent.path)||File.symlink?(destent.path))ent.copydestent.pathend,procdo|ent|destent =Entry_.new(dest,ent.rel,false)ent.copy_metadatadestent.pathifpreserveend)end
Recursively copies files fromsrc todest.
Argumentssrc anddest should beinterpretable as paths.
Ifsrc is the path to a file, copiessrc todest:
FileUtils.touch('src0.txt')File.exist?('dest0.txt')# => falseFileUtils.copy_entry('src0.txt','dest0.txt')File.file?('dest0.txt')# => true
Ifsrc is a directory, recursively copiessrc todest:
tree('src1')# => src1# |-- dir0# | |-- src0.txt# | `-- src1.txt# `-- dir1# |-- src2.txt# `-- src3.txtFileUtils.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.
Optional arguments:
dereference_root- ifsrcis a symbolic link, follows the link (falseby default).preserve- preserves file times (falseby default).remove_destination- removesdestbefore copying files (falseby default).
Related:methods for copying.
Source
# File lib/fileutils.rb, line 1073defcopy_file(src,dest,preserve =false,dereference =true)ent =Entry_.new(src,nil,dereference)ent.copy_filedestent.copy_metadatadestifpreserveend
Copies file fromsrc todest, which should not be directories.
Argumentssrc anddest should beinterpretable as paths.
Examples:
FileUtils.touch('src0.txt')FileUtils.copy_file('src0.txt','dest0.txt')File.file?('dest0.txt')# => true
Optional arguments:
dereference- ifsrcis a symbolic link, follows the link (trueby default).preserve- preserves file times (falseby default).remove_destination- removesdestbefore copying files (falseby default).
Related:methods for copying.
Source
# File lib/fileutils.rb, line 1085defcopy_stream(src,dest)IO.copy_stream(src,dest)end
Copies IO streamsrc to IO streamdest viaIO.copy_stream.
Related:methods for copying.
Source
# File lib/fileutils.rb, line 870defcp(src,dest,preserve:nil,noop:nil,verbose:nil)fu_output_message"cp#{preserve ? ' -p' : ''} #{[src,dest].flatten.join ' '}"ifverbosereturnifnoopfu_each_src_dest(src,dest)do|s,d|copy_files,d,preserveendend
Copies files.
Argumentssrc (a single path or an array of paths) anddest (a single path) should beinterpretable as paths.
Ifsrc is the path to a file anddest is not the path to a directory, copiessrc todest:
FileUtils.touch('src0.txt')File.exist?('dest0.txt')# => falseFileUtils.cp('src0.txt','dest0.txt')File.file?('dest0.txt')# => true
Ifsrc is the path to a file anddest is the path to a directory, copiessrc todest/src:
FileUtils.touch('src1.txt')FileUtils.mkdir('dest1')FileUtils.cp('src1.txt','dest1')File.file?('dest1/src1.txt')# => true
Ifsrc is an array of paths to files anddest is the path to a directory, copies from eachsrc todest:
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')# => trueFile.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:
cpsrc0.txtdest0.txtcpsrc1.txtdest1cpsrc2.txtsrc2.datdest2
Raises an exception ifsrc is a directory.
Related:methods for copying.
Source
# File lib/fileutils.rb, line 628defcp_lr(src,dest,noop:nil,verbose:nil,dereference_root:true,remove_destination:false)fu_output_message"cp -lr#{remove_destination ? ' --remove-destination' : ''} #{[src,dest].flatten.join ' '}"ifverbosereturnifnoopfu_each_src_dest(src,dest)do|s,d|link_entrys,d,dereference_root,remove_destinationendend
Createshard links.
Argumentssrc (a single path or an array of paths) anddest (a single path) should beinterpretable as paths.
Ifsrc is the path to a directory anddest does not exist, creates linksdest and descendents pointing tosrc and its descendents:
tree('src0')# => src0# |-- sub0# | |-- src0.txt# | `-- src1.txt# `-- sub1# |-- src2.txt# `-- src3.txtFile.exist?('dest0')# => falseFileUtils.cp_lr('src0','dest0')tree('dest0')# => dest0# |-- sub0# | |-- src0.txt# | `-- src1.txt# `-- sub1# |-- src2.txt# `-- src3.txt
Ifsrc anddest are both paths to directories, creates linksdest/src and descendents pointing tosrc and its descendents:
tree('src1')# => src1# |-- sub0# | |-- src0.txt# | `-- src1.txt# `-- sub1# |-- src2.txt# `-- src3.txtFileUtils.mkdir('dest1')FileUtils.cp_lr('src1','dest1')tree('dest1')# => dest1# `-- src1# |-- sub0# | |-- src0.txt# | `-- src1.txt# `-- sub1# |-- src2.txt# `-- src3.txt
Ifsrc is an array of paths to entries anddest is the path to a directory, for each pathfilepath insrc, creates a link atdest/filepath pointing to that path:
tree('src2')# => src2# |-- sub0# | |-- src0.txt# | `-- src1.txt# `-- sub1# |-- src2.txt# `-- src3.txtFileUtils.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- ifsrcis a symbolic link, does not dereference it.noop: true- does not create links.remove_destination: true- removesdestbefore 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 dest0cp -lr src1 dest1cp -lr src2/sub0 src2/sub1 dest2
Raises an exception ifdest is the path to an existing file or directory and keyword argumentremove_destination: true is not given.
Related:methods for copying.
Source
# File lib/fileutils.rb, line 982defcp_r(src,dest,preserve:nil,noop:nil,verbose:nil,dereference_root:true,remove_destination:nil)fu_output_message"cp -r#{preserve ? 'p' : ''}#{remove_destination ? ' --remove-destination' : ''} #{[src,dest].flatten.join ' '}"ifverbosereturnifnoopfu_each_src_dest(src,dest)do|s,d|copy_entrys,d,preserve,dereference_root,remove_destinationendend
Recursively copies files.
Argumentssrc (a single path or an array of paths) anddest (a single path) should beinterpretable as paths.
The mode, owner, and group are retained in the copy; to change those, useFileUtils.install instead.
Ifsrc is the path to a file anddest is not the path to a directory, copiessrc todest:
FileUtils.touch('src0.txt')File.exist?('dest0.txt')# => falseFileUtils.cp_r('src0.txt','dest0.txt')File.file?('dest0.txt')# => true
Ifsrc is the path to a file anddest is the path to a directory, copiessrc todest/src:
FileUtils.touch('src1.txt')FileUtils.mkdir('dest1')FileUtils.cp_r('src1.txt','dest1')File.file?('dest1/src1.txt')# => true
Ifsrc is the path to a directory anddest does not exist, recursively copiessrc todest:
tree('src2')# => src2# |-- dir0# | |-- src0.txt# | `-- src1.txt# `-- dir1# |-- src2.txt# `-- src3.txtFileUtils.exist?('dest2')# => falseFileUtils.cp_r('src2','dest2')tree('dest2')# => dest2# |-- dir0# | |-- src0.txt# | `-- src1.txt# `-- dir1# |-- src2.txt# `-- src3.txt
Ifsrc anddest are paths to directories, recursively copiessrc todest/src:
tree('src3')# => src3# |-- dir0# | |-- src0.txt# | `-- src1.txt# `-- dir1# |-- src2.txt# `-- src3.txtFileUtils.mkdir('dest3')FileUtils.cp_r('src3','dest3')tree('dest3')# => dest3# `-- src3# |-- dir0# | |-- src0.txt# | `-- src1.txt# `-- dir1# |-- src2.txt# `-- src3.txt
Ifsrc is an array of paths anddest is a directory, recursively copies from each path insrc todest; the paths insrc may point to files and/or directories.
Keyword arguments:
dereference_root: false- ifsrcis a symbolic link, does not dereference it.noop: true- does not copy files.preserve: true- preserves file times.remove_destination: true- removesdestbefore 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.txtcp -r src1.txt dest1cp -r src2 dest2cp -r src3 dest3
Raises an exception ofsrc is the path to a directory anddest is the path to a file.
Related:methods for copying.
Source
# File lib/fileutils.rb, line 2595defself.have_option?(mid,opt)li =OPT_TABLE[mid.to_s]orraiseArgumentError,"no such method: #{mid}"li.include?(opt)end
Returnstrue if methodmid accepts the given optionopt,false otherwise; the arguments may be strings or symbols:
FileUtils.have_option?(:chmod,:noop)# => trueFileUtils.have_option?('chmod','secure')# => false
Source
# File lib/fileutils.rb, line 1607definstall(src,dest,mode:nil,owner:nil,group:nil,preserve:nil,noop:nil,verbose:nil)ifverbosemsg =+"install -c"msg<<' -p'ifpreservemsg<<' -m '<<mode_to_s(mode)ifmodemsg<<" -o #{owner}"ifownermsg<<" -g #{group}"ifgroupmsg<<' '<< [src,dest].flatten.join(' ')fu_output_messagemsgendreturnifnoopuid =fu_get_uid(owner)gid =fu_get_gid(group)fu_each_src_dest(src,dest)do|s,d|st =File.stat(s)unlessFile.exist?(d)andcompare_file(s,d)remove_filed,trueifd.end_with?('/')mkdir_pdcopy_files,d+File.basename(s)elsemkdir_pFile.expand_path('..',d)copy_files,dendFile.utimest.atime,st.mtime,difpreserveFile.chmodfu_mode(mode,st),difmodeFile.chownuid,gid,difuidorgidendendend
Copies a file entry. Seeinstall(1).
Argumentssrc (a single path or an array of paths) anddest (a single path) should beinterpretable as paths;
If the entry atdest does not exist, copies fromsrc todest:
File.read('src0.txt')# => "aaa\n"File.exist?('dest0.txt')# => falseFileUtils.install('src0.txt','dest0.txt')File.read('dest0.txt')# => "aaa\n"
Ifdest is a file entry, copies fromsrc todest, 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"
Ifdest is a directory entry, copies fromsrc todest/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"
Ifsrc is an array of paths anddest points to a directory, copies each pathpath insrc todest/path:
File.file?('src3.txt')# => trueFile.file?('src3.dat')# => trueFileUtils.mkdir('dest3')FileUtils.install(['src3.txt','src3.dat'],'dest3')File.file?('dest3/src3.txt')# => trueFile.file?('dest3/src3.dat')# => true
Keyword arguments:
group:group- changes the group if notnil, usingFile.chown.mode:permissions- changes the permissions. usingFile.chmod.noop: true- does not copy entries; returnsnil.owner:owner- changes the owner if notnil, usingFile.chown.preserve: true- preserve timestamps usingFile.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.txtinstall -c src1.txt dest1.txtinstall -c src2.txt dest2
Related:methods for copying.
Source
# File lib/fileutils.rb, line 809deflink_entry(src,dest,dereference_root =false,remove_destination =false)Entry_.new(src,nil,dereference_root).traversedo|ent|destent =Entry_.new(dest,ent.rel,false)File.unlinkdestent.pathifremove_destination&&File.file?(destent.path)ent.linkdestent.pathendend
Createshard links; returnsnil.
Argumentssrc anddest should beinterpretable as paths.
Ifsrc is the path to a file anddest does not exist, creates a hard link atdest pointing tosrc:
FileUtils.touch('src0.txt')File.exist?('dest0.txt')# => falseFileUtils.link_entry('src0.txt','dest0.txt')File.file?('dest0.txt')# => true
Ifsrc is the path to a directory anddest does not exist, recursively creates hard links atdest pointing to paths insrc:
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')# => trueFileUtils.link_entry('src1','dest1')File.file?('dest1/dir0/t0.txt')# => trueFile.file?('dest1/dir0/t1.txt')# => trueFile.file?('dest1/dir1/t2.txt')# => trueFile.file?('dest1/dir1/t3.txt')# => true
Optional arguments:
dereference_root- dereferencessrcif it is a symbolic link (falseby default).remove_destination- removesdestbefore creating links (falseby default).
Raises an exception ifdest is the path to an existing file or directory and optional argumentremove_destination is not given.
Related:FileUtils.ln (has different options).
Source
# File lib/fileutils.rb, line 517defln(src,dest,force:nil,noop:nil,verbose:nil)fu_output_message"ln#{force ? ' -f' : ''} #{[src,dest].flatten.join ' '}"ifverbosereturnifnoopfu_each_src_dest0(src,dest)do|s,d|remove_filed,trueifforceFile.links,dendend
Createshard links.
Argumentssrc (a single path or an array of paths) anddest (a single path) should beinterpretable as paths.
Whensrc is the path to an existing file anddest is the path to a non-existent file, creates a hard link atdest pointing tosrc; returns zero:
Dir.children('tmp0/')# => ["t.txt"]Dir.children('tmp1/')# => []FileUtils.ln('tmp0/t.txt','tmp1/t.lnk')# => 0Dir.children('tmp1/')# => ["t.lnk"]
Whensrc is the path to an existing file anddest is the path to an existing directory, creates a hard link atdest/src pointing tosrc; returns zero:
Dir.children('tmp2')# => ["t.dat"]Dir.children('tmp3')# => []FileUtils.ln('tmp2/t.dat','tmp3')# => 0Dir.children('tmp3')# => ["t.dat"]
Whensrc is an array of paths to existing files anddest is the path to an existing directory, then for each pathtarget insrc, creates a hard link atdest/target pointing totarget; returnssrc:
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- overwritesdestif 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.lnkln tmp2/t.dat tmp3ln tmp0/t.txt tmp2/t.dat tmp4/
Raises an exception ifdest is the path to an existing file and keyword argumentforce is nottrue.
Related:FileUtils.link_entry (has different options).
Source
# File lib/fileutils.rb, line 707defln_s(src,dest,force:nil,relative:false,target_directory:true,noop:nil,verbose:nil)ifrelativereturnln_sr(src,dest,force:force,target_directory:target_directory,noop:noop,verbose:verbose)endfu_output_message"ln -s#{force ? 'f' : ''}#{ target_directory ? '' : 'T'} #{[src,dest].flatten.join ' '}"ifverbosereturnifnoopfu_each_src_dest0(src,dest,target_directory)do|s,d|remove_filed,trueifforceFile.symlinks,dendend
Createssymbolic links.
Argumentssrc (a single path or an array of paths) anddest (a single path) should beinterpretable as paths.
Ifsrc is the path to an existing file:
When
destis the path to a non-existent file, creates a symbolic link atdestpointing tosrc:FileUtils.touch('src0.txt')File.exist?('dest0.txt')# => falseFileUtils.ln_s('src0.txt','dest0.txt')File.symlink?('dest0.txt')# => true
When
destis the path to an existing file, creates a symbolic link atdestpointing tosrcif and only if keyword argumentforce: trueis 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')# => trueFileUtils.ln_s('src1.txt','dest1.txt')# Raises Errno::EEXIST.
Ifdest is the path to a directory, creates a symbolic link atdest/src pointing tosrc:
FileUtils.touch('src2.txt')FileUtils.mkdir('destdir2')FileUtils.ln_s('src2.txt','destdir2')File.symlink?('destdir2/src2.txt')# => true
Ifsrc is an array of paths to existing files anddest is a directory, for each childchild insrc creates a symbolic linkdest/child pointing tochild:
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')# => trueFile.symlink?('destdir3/src1.txt')# => true
Keyword arguments:
force: true- overwritesdestif 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.txtln -s src1.txt destdir1ln -sf src2.txt dest2.txtln -s srcdir3/src0.txt srcdir3/src1.txt destdir3
Related:FileUtils.ln_sf.
Source
# File lib/fileutils.rb, line 726defln_sf(src,dest,noop:nil,verbose:nil)ln_ssrc,dest,force:true,noop:noop,verbose:verboseend
LikeFileUtils.ln_s, but always with keyword argumentforce: true given.
Source
# File lib/fileutils.rb, line 733defln_sr(src,dest,target_directory:true,force:nil,noop:nil,verbose:nil)cmd ="ln -s#{force ? 'f' : ''}#{target_directory ? '' : 'T'}"ifverbosefu_each_src_dest0(src,dest,target_directory)do|s,d|iftarget_directoryparent =File.dirname(d)destdirs =fu_split_path(parent)real_ddirs =fu_split_path(File.realpath(parent))elsedestdirs||=fu_split_path(dest)real_ddirs||=fu_split_path(File.realdirpath(dest))endsrcdirs =fu_split_path(s)i =fu_common_components(srcdirs,destdirs)n =destdirs.size-in-=1unlesstarget_directorylink1 =fu_clean_components(*Array.new([n,0].max,'..'),*srcdirs[i..-1])beginreal_sdirs =fu_split_path(File.realdirpath(s))rescuenilrescueelsei =fu_common_components(real_sdirs,real_ddirs)n =real_ddirs.size-in-=1unlesstarget_directorylink2 =fu_clean_components(*Array.new([n,0].max,'..'),*real_sdirs[i..-1])link1 =link2iflink1.size>link2.sizeends =File.join(link1)fu_output_message [cmd,s,d].flatten.join(' ')ifverbosenextifnoopremove_filed,trueifforceFile.symlinks,dendend
LikeFileUtils.ln_s, but create links relative todest.
Source
# File lib/fileutils.rb, line 317defmkdir(list,mode:nil,noop:nil,verbose:nil)list =fu_list(list)fu_output_message"mkdir #{mode ? ('-m %03o ' % mode) : ''}#{list.join ' '}"ifverbosereturnifnooplist.eachdo|dir|fu_mkdirdir,modeendend
Creates directories at the paths in the givenlist (a single path or an array of paths); returnslist if it is an array,[list] otherwise.
Argumentlist or its elements should beinterpretable as paths.
With no keyword arguments, creates a directory at eachpath inlist by calling:Dir.mkdir(path, mode); seeDir.mkdir:
FileUtils.mkdir(%w[tmp0 tmp1])# => ["tmp0", "tmp1"]FileUtils.mkdir('tmp4')# => ["tmp4"]
Keyword arguments:
mode:mode- also callsFile.chmod(mode, path); seeFile.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 tmp1mkdir -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.
Source
# File lib/fileutils.rb, line 366defmkdir_p(list,mode:nil,noop:nil,verbose:nil)list =fu_list(list)fu_output_message"mkdir -p #{mode ? ('-m %03o ' % mode) : ''}#{list.join ' '}"ifverbosereturn*listifnooplist.eachdo|item|path =remove_trailing_slash(item)stack = []untilFile.directory?(path)||File.dirname(path)==pathstack.pushpathpath =File.dirname(path)endstack.reverse_eachdo|dir|beginfu_mkdirdir,moderescueSystemCallErrorraiseunlessFile.directory?(dir)endendendreturn*listend
Creates directories at the paths in the givenlist (a single path or an array of paths), also creating ancestor directories as needed; returnslist if it is an array,[list] otherwise.
Argumentlist or its elements should beinterpretable as paths.
With no keyword arguments, creates a directory at eachpath inlist, along with any needed ancestor directories, by calling:Dir.mkdir(path, mode); seeDir.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); seeFile.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 tmp1mkdir -p -m 700 tmp2 tmp3
Raises an exception if for any reason a directory cannot be created.
FileUtils.mkpath andFileUtils.makedirs are aliases forFileUtils.mkdir_p.
Related:FileUtils.mkdir.
Source
# File lib/fileutils.rb, line 1154defmv(src,dest,force:nil,noop:nil,verbose:nil,secure:nil)fu_output_message"mv#{force ? ' -f' : ''} #{[src,dest].flatten.join ' '}"ifverbosereturnifnoopfu_each_src_dest(src,dest)do|s,d|destent =Entry_.new(d,nil,true)beginifdestent.exist?ifdestent.directory?raiseErrno::EEXIST,dendendbeginFile.renames,drescueErrno::EXDEV,Errno::EPERM# move from unencrypted to encrypted dir (ext4)copy_entrys,d,trueifsecureremove_entry_secures,forceelseremove_entrys,forceendendrescueSystemCallErrorraiseunlessforceendendend
Moves entries.
Argumentssrc (a single path or an array of paths) anddest (a single path) should beinterpretable as paths.
Ifsrc anddest are on different file systems, first copies, then removessrc.
May cause a local vulnerability if not called with keyword argumentsecure: true; seeAvoiding the TOCTTOU Vulnerability.
Ifsrc is the path to a single file or directory anddest does not exist, movessrc todest:
tree('src0')# => src0# |-- src0.txt# `-- src1.txtFile.exist?('dest0')# => falseFileUtils.mv('src0','dest0')File.exist?('src0')# => falsetree('dest0')# => dest0# |-- src0.txt# `-- src1.txt
Ifsrc is an array of paths to files and directories anddest is the path to a directory, copies from each path in the array todest:
File.file?('src1.txt')# => truetree('src1')# => src1# |-- src.dat# `-- src.txtDir.empty?('dest1')# => trueFileUtils.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, ifsrcanddestare on different file systems), ignores raised exceptions ofStandardErrorand its descendants.noop: true- does not move files.secure: true- removessrcsecurely; see details atFileUtils.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:
mvsrc0dest0mvsrc1.txtsrc1dest1
Source
# File lib/fileutils.rb, line 2585defself.optionsOPT_TABLE.values.flatten.uniq.map {|sym|sym.to_s }end
Returns an array of the string keyword names:
FileUtils.options.take(3)# => ["noop", "verbose", "force"]
Source
# File lib/fileutils.rb, line 2606defself.options_of(mid)OPT_TABLE[mid.to_s].map {|sym|sym.to_s }end
Returns an array of the string keyword name for methodmid; the argument may be a string or a symbol:
FileUtils.options_of(:rm)# => ["force", "noop", "verbose"]FileUtils.options_of('mv')# => ["force", "noop", "verbose", "secure"]
Source
# File lib/fileutils.rb, line 198defpwdDir.pwdend
Returns a string containing the path to the current directory:
FileUtils.pwd# => "/rdoc/fileutils"
Related:FileUtils.cd.
Source
# File lib/fileutils.rb, line 1489defremove_dir(path,force =false)raiseErrno::ENOTDIR,pathunlessforceorFile.directory?(path)remove_entrypath,forceend
Recursively removes the directory entry given bypath, which should be the entry for a regular file, a symbolic link, or a directory.
Argumentpath should beinterpretable as a path.
Optional argumentforce specifies whether to ignore raised exceptions ofStandardError and its descendants.
Related:methods for deleting.
Source
# File lib/fileutils.rb, line 1446defremove_entry(path,force =false)Entry_.new(path).postorder_traversedo|ent|beginent.removerescueraiseunlessforceendendrescueraiseunlessforceend
Removes the entry given bypath, which should be the entry for a regular file, a symbolic link, or a directory.
Argumentpath should beinterpretable as a path.
Optional argumentforce specifies whether to ignore raised exceptions ofStandardError and its descendants.
Related:FileUtils.remove_entry_secure.
Source
# File lib/fileutils.rb, line 1348defremove_entry_secure(path,force =false)unlessfu_have_symlink?remove_entrypath,forcereturnendfullpath =File.expand_path(path)st =File.lstat(fullpath)unlessst.directory?File.unlinkfullpathreturnend# is a directory.parent_st =File.stat(File.dirname(fullpath))unlessparent_st.world_writable?remove_entrypath,forcereturnendunlessparent_st.sticky?raiseArgumentError,"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 rooteuid =Process.euiddot_file =fullpath+"/."beginFile.open(dot_file) {|f|unlessfu_stat_identical_entry?(st,f.stat)# symlink (TOC-to-TOU attack?)File.unlinkfullpathreturnendf.chowneuid,-1f.chmod0700 }rescueErrno::EISDIR# JRuby in non-native mode can't open files as dirsFile.lstat(dot_file).tap {|fstat|unlessfu_stat_identical_entry?(st,fstat)# symlink (TOC-to-TOU attack?)File.unlinkfullpathreturnendFile.chowneuid,-1,dot_fileFile.chmod0700,dot_file }endunlessfu_stat_identical_entry?(st,File.lstat(fullpath))# TOC-to-TOU attack?File.unlinkfullpathreturnend# ---- tree root is frozen ----root =Entry_.new(path)root.preorder_traversedo|ent|ifent.directory?ent.chowneuid,-1ent.chmod0700endendroot.postorder_traversedo|ent|beginent.removerescueraiseunlessforceendendrescueraiseunlessforceend
Securely removes the entry given bypath, which should be the entry for a regular file, a symbolic link, or a directory.
Argumentpath should beinterpretable as a path.
Avoids a local vulnerability that can exist in certain circumstances; seeAvoiding the TOCTTOU Vulnerability.
Optional argumentforce specifies whether to ignore raised exceptions ofStandardError and its descendants.
Related:methods for deleting.
Source
# File lib/fileutils.rb, line 1470defremove_file(path,force =false)Entry_.new(path).remove_filerescueraiseunlessforceend
Removes the file entry given bypath, which should be the entry for a regular file or a symbolic link.
Argumentpath should beinterpretable as a path.
Optional argumentforce specifies whether to ignore raised exceptions ofStandardError and its descendants.
Related:methods for deleting.
Source
# File lib/fileutils.rb, line 1213defrm(list,force:nil,noop:nil,verbose:nil)list =fu_list(list)fu_output_message"rm#{force ? ' -f' : ''} #{list.join ' '}"ifverbosereturnifnooplist.eachdo|path|remove_filepath,forceendend
Removes entries at the paths in the givenlist (a single path or an array of paths) returnslist, if it is an array,[list] otherwise.
Argumentlist or its elements should beinterpretable as paths.
With no keyword arguments, removes files at the paths given inlist:
FileUtils.touch(['src0.txt','src0.dat'])FileUtils.rm(['src0.dat','src0.txt'])# => ["src0.dat", "src0.txt"]
Keyword arguments:
force: true- ignores raised exceptions ofStandardErrorand 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:
rmsrc0.datsrc0.txt
Related:methods for deleting.
Source
# File lib/fileutils.rb, line 1238defrm_f(list,noop:nil,verbose:nil)rmlist,force:true,noop:noop,verbose:verboseend
Equivalent to:
FileUtils.rm(list,force:true,**kwargs)
Argumentlist (a single path or an array of paths) should beinterpretable as paths.
SeeFileUtils.rm for keyword arguments.
Related:methods for deleting.
Source
# File lib/fileutils.rb, line 1296defrm_r(list,force:nil,noop:nil,verbose:nil,secure:nil)list =fu_list(list)fu_output_message"rm -r#{force ? 'f' : ''} #{list.join ' '}"ifverbosereturnifnooplist.eachdo|path|ifsecureremove_entry_securepath,forceelseremove_entrypath,forceendendend
Removes entries at the paths in the givenlist (a single path or an array of paths); returnslist, if it is an array,[list] otherwise.
Argumentlist or its elements should beinterpretable as paths.
May cause a local vulnerability if not called with keyword argumentsecure: true; seeAvoiding 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')# => falseFile.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.txtFileUtils.rm_r('src1')File.exist?('src1')# => false
Keyword arguments:
force: true- ignores raised exceptions ofStandardErrorand its descendants.noop: true- does not remove entries; returnsnil.secure: true- removessrcsecurely; see details atFileUtils.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.txtrm -r src1
Related:methods for deleting.
Source
# File lib/fileutils.rb, line 1325defrm_rf(list,noop:nil,verbose:nil,secure:nil)rm_rlist,force:true,noop:noop,verbose:verbose,secure:secureend
Equivalent to:
FileUtils.rm_r(list,force:true,**kwargs)
Argumentlist or its elements should beinterpretable as paths.
May cause a local vulnerability if not called with keyword argumentsecure: true; seeAvoiding the TOCTTOU Vulnerability.
SeeFileUtils.rm_r for keyword arguments.
Related:methods for deleting.
Source
# File lib/fileutils.rb, line 443defrmdir(list,parents:nil,noop:nil,verbose:nil)list =fu_list(list)fu_output_message"rmdir #{parents ? '-p ' : ''}#{list.join ' '}"ifverbosereturnifnooplist.eachdo|dir|Dir.rmdir(dir =remove_trailing_slash(dir))ifparentsbeginuntil (parent =File.dirname(dir))=='.'orparent==dirdir =parentDir.rmdir(dir)endrescueErrno::ENOTEMPTY,Errno::EEXIST,Errno::ENOENTendendendend
Removes directories at the paths in the givenlist (a single path or an array of paths); returnslist, if it is an array,[list] otherwise.
Argumentlist or its elements should beinterpretable as paths.
With no keyword arguments, removes the directory at eachpath inlist, by calling:Dir.rmdir(path); seeDir.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/tmp3rmdir -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.
Source
# File lib/fileutils.rb, line 2004deftouch(list,noop:nil,verbose:nil,mtime:nil,nocreate:nil)list =fu_list(list)t =mtimeifverbosefu_output_message"touch #{nocreate ? '-c ' : ''}#{t ? t.strftime('-t %Y%m%d%H%M.%S ') : ''}#{list.join ' '}"endreturnifnooplist.eachdo|path|created =nocreatebeginFile.utime(t,t,path)rescueErrno::ENOENTraiseifcreatedFile.open(path,'a') { ; }created =trueretryiftendendend
Updates modification times (mtime) and access times (atime) of the entries given by the paths inlist (a single path or an array of paths); returnslist if it is an array,[list] otherwise.
By default, creates an empty file for any path to a non-existent entry; use keyword argumentnocreate to raise an exception instead.
Argumentlist or its elements should beinterpretable as paths.
Examples:
# Single path.f =File.new('src0.txt')# Existing file.f.atime# => 2022-06-10 11:11:21.200277 -0700f.mtime# => 2022-06-10 11:11:21.200277 -0700FileUtils.touch('src0.txt')f =File.new('src0.txt')f.atime# => 2022-06-11 08:28:09.8185343 -0700f.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:
touchsrc0.txttouchsrc0.txtsrc0.dattouchsrc0.txt
Related:FileUtils.uptodate?.
Source
# File lib/fileutils.rb, line 265defuptodate?(new,old_list)returnfalseunlessFile.exist?(new)new_time =File.mtime(new)old_list.eachdo|old|ifFile.exist?(old)returnfalseunlessnew_time>File.mtime(old)endendtrueend
Returnstrue if the file at pathnew is newer than all the files at paths in arrayold_list;false otherwise.
Argumentnew and the elements ofold_list should beinterpretable as paths:
FileUtils.uptodate?('Rakefile', ['Gemfile','README.md'])# => trueFileUtils.uptodate?('Gemfile', ['Rakefile','README.md'])# => false
A non-existent file is considered to be infinitely old.
Related:FileUtils.touch.
Private Instance Methods
Source
# File lib/fileutils.rb, line 239defcd(dir,verbose:nil,&block)# :yield: dirfu_output_message"cd #{dir}"ifverboseresult =Dir.chdir(dir,&block)fu_output_message'cd -'ifverboseandblockresultend
Changes the working directory to the givendir, which should beinterpretable as a path:
With no block given, changes the current directory to the directory atdir; 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 atdir, calls the block with argumentdir, 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.
Source
# File lib/fileutils.rb, line 1801defchmod(mode,list,noop:nil,verbose:nil)list =fu_list(list)fu_output_messagesprintf('chmod %s %s',mode_to_s(mode),list.join(' '))ifverbosereturnifnooplist.eachdo|path|Entry_.new(path).chmod(fu_mode(mode,path))endend
Changes permissions on the entries at the paths given inlist (a single path or an array of paths) to the permissions given bymode; returnslist 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.
Argumentlist or its elements should beinterpretable as paths.
Argumentmode 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:targetsmay 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.
operatormay 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.txtchmod 644 src0.txt src0.datchmod u=wrx,go=rx src1.txtchmod u=wrx,go=rx /usr/bin/ruby
Related:FileUtils.chmod_R.
Source
# File lib/fileutils.rb, line 1813defchmod_R(mode,list,noop:nil,verbose:nil,force:nil)list =fu_list(list)fu_output_messagesprintf('chmod -R%s %s %s', (force?'f':''),mode_to_s(mode),list.join(' '))ifverbosereturnifnooplist.eachdo|root|Entry_.new(root).traversedo|ent|beginent.chmod(fu_mode(mode,ent.path))rescueraiseunlessforceendendendend
LikeFileUtils.chmod, but changes permissions recursively.
Source
# File lib/fileutils.rb, line 1894defchown(user,group,list,noop:nil,verbose:nil)list =fu_list(list)fu_output_messagesprintf('chown %s %s', (group?"#{user}:#{group}":user||':'),list.join(' '))ifverbosereturnifnoopuid =fu_get_uid(user)gid =fu_get_gid(group)list.eachdo|path|Entry_.new(path).chownuid,gidendend
Changes the owner and group on the entries at the paths given inlist (a single path or an array of paths) to the givenuser andgroup; returnslist 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.
Argumentlist or its elements should beinterpretable as paths.
User and group:
Argument
usermay be a user name or a user id; ifnilor-1, the user is not changed.Argument
groupmay be a group name or a group id; ifnilor-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# => 1004File.stat('src0.txt').gid# => 1004FileUtils.chown('user2','group1','src0.txt')File.stat('src0.txt').uid# => 1006File.stat('src0.txt').gid# => 1005# User and group as uid and gid.FileUtils.chown(1004,1004,'src0.txt')File.stat('src0.txt').uid# => 1004File.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.txtchown 1004:1004 src0.txtchown 1006:1005 src0.txt src0.datchown user2:group1 src0.txtchown user2:group1 .
Related:FileUtils.chown_R.
Source
# File lib/fileutils.rb, line 1910defchown_R(user,group,list,noop:nil,verbose:nil,force:nil)list =fu_list(list)fu_output_messagesprintf('chown -R%s %s %s', (force?'f':''), (group?"#{user}:#{group}":user||':'),list.join(' '))ifverbosereturnifnoopuid =fu_get_uid(user)gid =fu_get_gid(group)list.eachdo|root|Entry_.new(root).traversedo|ent|beginent.chownuid,gidrescueraiseunlessforceendendendend
LikeFileUtils.chown, but changes owner and group recursively.
Source
# File lib/fileutils.rb, line 1505defcompare_file(a,b)returnfalseunlessFile.size(a)==File.size(b)File.open(a,'rb') {|fa|File.open(b,'rb') {|fb|returncompare_stream(fa,fb) } }end
Returnstrue if the contents of filesa andb are identical,false otherwise.
Argumentsa andb should beinterpretable as a path.
FileUtils.identical? andFileUtils.cmp are aliases forFileUtils.compare_file.
Related:FileUtils.compare_stream.
Source
# File lib/fileutils.rb, line 1528defcompare_stream(a,b)bsize =fu_stream_blksize(a,b)sa =String.new(capacity:bsize)sb =String.new(capacity:bsize)begina.read(bsize,sa)b.read(bsize,sb)returntrueifsa.empty?&&sb.empty?endwhilesa==sbfalseend
Returnstrue if the contents of streamsa andb are identical,false otherwise.
Argumentsa andb should beinterpretable as a path.
Related:FileUtils.compare_file.
Source
# File lib/fileutils.rb, line 1037defcopy_entry(src,dest,preserve =false,dereference_root =false,remove_destination =false)ifdereference_rootsrc =File.realpath(src)endEntry_.new(src,nil,false).wrap_traverse(procdo|ent|destent =Entry_.new(dest,ent.rel,false)File.unlinkdestent.pathifremove_destination&& (File.file?(destent.path)||File.symlink?(destent.path))ent.copydestent.pathend,procdo|ent|destent =Entry_.new(dest,ent.rel,false)ent.copy_metadatadestent.pathifpreserveend)end
Recursively copies files fromsrc todest.
Argumentssrc anddest should beinterpretable as paths.
Ifsrc is the path to a file, copiessrc todest:
FileUtils.touch('src0.txt')File.exist?('dest0.txt')# => falseFileUtils.copy_entry('src0.txt','dest0.txt')File.file?('dest0.txt')# => true
Ifsrc is a directory, recursively copiessrc todest:
tree('src1')# => src1# |-- dir0# | |-- src0.txt# | `-- src1.txt# `-- dir1# |-- src2.txt# `-- src3.txtFileUtils.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.
Optional arguments:
dereference_root- ifsrcis a symbolic link, follows the link (falseby default).preserve- preserves file times (falseby default).remove_destination- removesdestbefore copying files (falseby default).
Related:methods for copying.
Source
# File lib/fileutils.rb, line 1073defcopy_file(src,dest,preserve =false,dereference =true)ent =Entry_.new(src,nil,dereference)ent.copy_filedestent.copy_metadatadestifpreserveend
Copies file fromsrc todest, which should not be directories.
Argumentssrc anddest should beinterpretable as paths.
Examples:
FileUtils.touch('src0.txt')FileUtils.copy_file('src0.txt','dest0.txt')File.file?('dest0.txt')# => true
Optional arguments:
dereference- ifsrcis a symbolic link, follows the link (trueby default).preserve- preserves file times (falseby default).remove_destination- removesdestbefore copying files (falseby default).
Related:methods for copying.
Source
# File lib/fileutils.rb, line 1085defcopy_stream(src,dest)IO.copy_stream(src,dest)end
Copies IO streamsrc to IO streamdest viaIO.copy_stream.
Related:methods for copying.
Source
# File lib/fileutils.rb, line 870defcp(src,dest,preserve:nil,noop:nil,verbose:nil)fu_output_message"cp#{preserve ? ' -p' : ''} #{[src,dest].flatten.join ' '}"ifverbosereturnifnoopfu_each_src_dest(src,dest)do|s,d|copy_files,d,preserveendend
Copies files.
Argumentssrc (a single path or an array of paths) anddest (a single path) should beinterpretable as paths.
Ifsrc is the path to a file anddest is not the path to a directory, copiessrc todest:
FileUtils.touch('src0.txt')File.exist?('dest0.txt')# => falseFileUtils.cp('src0.txt','dest0.txt')File.file?('dest0.txt')# => true
Ifsrc is the path to a file anddest is the path to a directory, copiessrc todest/src:
FileUtils.touch('src1.txt')FileUtils.mkdir('dest1')FileUtils.cp('src1.txt','dest1')File.file?('dest1/src1.txt')# => true
Ifsrc is an array of paths to files anddest is the path to a directory, copies from eachsrc todest:
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')# => trueFile.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:
cpsrc0.txtdest0.txtcpsrc1.txtdest1cpsrc2.txtsrc2.datdest2
Raises an exception ifsrc is a directory.
Related:methods for copying.
Source
# File lib/fileutils.rb, line 628defcp_lr(src,dest,noop:nil,verbose:nil,dereference_root:true,remove_destination:false)fu_output_message"cp -lr#{remove_destination ? ' --remove-destination' : ''} #{[src,dest].flatten.join ' '}"ifverbosereturnifnoopfu_each_src_dest(src,dest)do|s,d|link_entrys,d,dereference_root,remove_destinationendend
Createshard links.
Argumentssrc (a single path or an array of paths) anddest (a single path) should beinterpretable as paths.
Ifsrc is the path to a directory anddest does not exist, creates linksdest and descendents pointing tosrc and its descendents:
tree('src0')# => src0# |-- sub0# | |-- src0.txt# | `-- src1.txt# `-- sub1# |-- src2.txt# `-- src3.txtFile.exist?('dest0')# => falseFileUtils.cp_lr('src0','dest0')tree('dest0')# => dest0# |-- sub0# | |-- src0.txt# | `-- src1.txt# `-- sub1# |-- src2.txt# `-- src3.txt
Ifsrc anddest are both paths to directories, creates linksdest/src and descendents pointing tosrc and its descendents:
tree('src1')# => src1# |-- sub0# | |-- src0.txt# | `-- src1.txt# `-- sub1# |-- src2.txt# `-- src3.txtFileUtils.mkdir('dest1')FileUtils.cp_lr('src1','dest1')tree('dest1')# => dest1# `-- src1# |-- sub0# | |-- src0.txt# | `-- src1.txt# `-- sub1# |-- src2.txt# `-- src3.txt
Ifsrc is an array of paths to entries anddest is the path to a directory, for each pathfilepath insrc, creates a link atdest/filepath pointing to that path:
tree('src2')# => src2# |-- sub0# | |-- src0.txt# | `-- src1.txt# `-- sub1# |-- src2.txt# `-- src3.txtFileUtils.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- ifsrcis a symbolic link, does not dereference it.noop: true- does not create links.remove_destination: true- removesdestbefore 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 dest0cp -lr src1 dest1cp -lr src2/sub0 src2/sub1 dest2
Raises an exception ifdest is the path to an existing file or directory and keyword argumentremove_destination: true is not given.
Related:methods for copying.
Source
# File lib/fileutils.rb, line 982defcp_r(src,dest,preserve:nil,noop:nil,verbose:nil,dereference_root:true,remove_destination:nil)fu_output_message"cp -r#{preserve ? 'p' : ''}#{remove_destination ? ' --remove-destination' : ''} #{[src,dest].flatten.join ' '}"ifverbosereturnifnoopfu_each_src_dest(src,dest)do|s,d|copy_entrys,d,preserve,dereference_root,remove_destinationendend
Recursively copies files.
Argumentssrc (a single path or an array of paths) anddest (a single path) should beinterpretable as paths.
The mode, owner, and group are retained in the copy; to change those, useFileUtils.install instead.
Ifsrc is the path to a file anddest is not the path to a directory, copiessrc todest:
FileUtils.touch('src0.txt')File.exist?('dest0.txt')# => falseFileUtils.cp_r('src0.txt','dest0.txt')File.file?('dest0.txt')# => true
Ifsrc is the path to a file anddest is the path to a directory, copiessrc todest/src:
FileUtils.touch('src1.txt')FileUtils.mkdir('dest1')FileUtils.cp_r('src1.txt','dest1')File.file?('dest1/src1.txt')# => true
Ifsrc is the path to a directory anddest does not exist, recursively copiessrc todest:
tree('src2')# => src2# |-- dir0# | |-- src0.txt# | `-- src1.txt# `-- dir1# |-- src2.txt# `-- src3.txtFileUtils.exist?('dest2')# => falseFileUtils.cp_r('src2','dest2')tree('dest2')# => dest2# |-- dir0# | |-- src0.txt# | `-- src1.txt# `-- dir1# |-- src2.txt# `-- src3.txt
Ifsrc anddest are paths to directories, recursively copiessrc todest/src:
tree('src3')# => src3# |-- dir0# | |-- src0.txt# | `-- src1.txt# `-- dir1# |-- src2.txt# `-- src3.txtFileUtils.mkdir('dest3')FileUtils.cp_r('src3','dest3')tree('dest3')# => dest3# `-- src3# |-- dir0# | |-- src0.txt# | `-- src1.txt# `-- dir1# |-- src2.txt# `-- src3.txt
Ifsrc is an array of paths anddest is a directory, recursively copies from each path insrc todest; the paths insrc may point to files and/or directories.
Keyword arguments:
dereference_root: false- ifsrcis a symbolic link, does not dereference it.noop: true- does not copy files.preserve: true- preserves file times.remove_destination: true- removesdestbefore 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.txtcp -r src1.txt dest1cp -r src2 dest2cp -r src3 dest3
Raises an exception ofsrc is the path to a directory anddest is the path to a file.
Related:methods for copying.
Source
# File lib/fileutils.rb, line 1607definstall(src,dest,mode:nil,owner:nil,group:nil,preserve:nil,noop:nil,verbose:nil)ifverbosemsg =+"install -c"msg<<' -p'ifpreservemsg<<' -m '<<mode_to_s(mode)ifmodemsg<<" -o #{owner}"ifownermsg<<" -g #{group}"ifgroupmsg<<' '<< [src,dest].flatten.join(' ')fu_output_messagemsgendreturnifnoopuid =fu_get_uid(owner)gid =fu_get_gid(group)fu_each_src_dest(src,dest)do|s,d|st =File.stat(s)unlessFile.exist?(d)andcompare_file(s,d)remove_filed,trueifd.end_with?('/')mkdir_pdcopy_files,d+File.basename(s)elsemkdir_pFile.expand_path('..',d)copy_files,dendFile.utimest.atime,st.mtime,difpreserveFile.chmodfu_mode(mode,st),difmodeFile.chownuid,gid,difuidorgidendendend
Copies a file entry. Seeinstall(1).
Argumentssrc (a single path or an array of paths) anddest (a single path) should beinterpretable as paths;
If the entry atdest does not exist, copies fromsrc todest:
File.read('src0.txt')# => "aaa\n"File.exist?('dest0.txt')# => falseFileUtils.install('src0.txt','dest0.txt')File.read('dest0.txt')# => "aaa\n"
Ifdest is a file entry, copies fromsrc todest, 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"
Ifdest is a directory entry, copies fromsrc todest/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"
Ifsrc is an array of paths anddest points to a directory, copies each pathpath insrc todest/path:
File.file?('src3.txt')# => trueFile.file?('src3.dat')# => trueFileUtils.mkdir('dest3')FileUtils.install(['src3.txt','src3.dat'],'dest3')File.file?('dest3/src3.txt')# => trueFile.file?('dest3/src3.dat')# => true
Keyword arguments:
group:group- changes the group if notnil, usingFile.chown.mode:permissions- changes the permissions. usingFile.chmod.noop: true- does not copy entries; returnsnil.owner:owner- changes the owner if notnil, usingFile.chown.preserve: true- preserve timestamps usingFile.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.txtinstall -c src1.txt dest1.txtinstall -c src2.txt dest2
Related:methods for copying.
Source
# File lib/fileutils.rb, line 809deflink_entry(src,dest,dereference_root =false,remove_destination =false)Entry_.new(src,nil,dereference_root).traversedo|ent|destent =Entry_.new(dest,ent.rel,false)File.unlinkdestent.pathifremove_destination&&File.file?(destent.path)ent.linkdestent.pathendend
Createshard links; returnsnil.
Argumentssrc anddest should beinterpretable as paths.
Ifsrc is the path to a file anddest does not exist, creates a hard link atdest pointing tosrc:
FileUtils.touch('src0.txt')File.exist?('dest0.txt')# => falseFileUtils.link_entry('src0.txt','dest0.txt')File.file?('dest0.txt')# => true
Ifsrc is the path to a directory anddest does not exist, recursively creates hard links atdest pointing to paths insrc:
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')# => trueFileUtils.link_entry('src1','dest1')File.file?('dest1/dir0/t0.txt')# => trueFile.file?('dest1/dir0/t1.txt')# => trueFile.file?('dest1/dir1/t2.txt')# => trueFile.file?('dest1/dir1/t3.txt')# => true
Optional arguments:
dereference_root- dereferencessrcif it is a symbolic link (falseby default).remove_destination- removesdestbefore creating links (falseby default).
Raises an exception ifdest is the path to an existing file or directory and optional argumentremove_destination is not given.
Related:FileUtils.ln (has different options).
Source
# File lib/fileutils.rb, line 517defln(src,dest,force:nil,noop:nil,verbose:nil)fu_output_message"ln#{force ? ' -f' : ''} #{[src,dest].flatten.join ' '}"ifverbosereturnifnoopfu_each_src_dest0(src,dest)do|s,d|remove_filed,trueifforceFile.links,dendend
Createshard links.
Argumentssrc (a single path or an array of paths) anddest (a single path) should beinterpretable as paths.
Whensrc is the path to an existing file anddest is the path to a non-existent file, creates a hard link atdest pointing tosrc; returns zero:
Dir.children('tmp0/')# => ["t.txt"]Dir.children('tmp1/')# => []FileUtils.ln('tmp0/t.txt','tmp1/t.lnk')# => 0Dir.children('tmp1/')# => ["t.lnk"]
Whensrc is the path to an existing file anddest is the path to an existing directory, creates a hard link atdest/src pointing tosrc; returns zero:
Dir.children('tmp2')# => ["t.dat"]Dir.children('tmp3')# => []FileUtils.ln('tmp2/t.dat','tmp3')# => 0Dir.children('tmp3')# => ["t.dat"]
Whensrc is an array of paths to existing files anddest is the path to an existing directory, then for each pathtarget insrc, creates a hard link atdest/target pointing totarget; returnssrc:
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- overwritesdestif 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.lnkln tmp2/t.dat tmp3ln tmp0/t.txt tmp2/t.dat tmp4/
Raises an exception ifdest is the path to an existing file and keyword argumentforce is nottrue.
Related:FileUtils.link_entry (has different options).
Source
# File lib/fileutils.rb, line 707defln_s(src,dest,force:nil,relative:false,target_directory:true,noop:nil,verbose:nil)ifrelativereturnln_sr(src,dest,force:force,target_directory:target_directory,noop:noop,verbose:verbose)endfu_output_message"ln -s#{force ? 'f' : ''}#{ target_directory ? '' : 'T'} #{[src,dest].flatten.join ' '}"ifverbosereturnifnoopfu_each_src_dest0(src,dest,target_directory)do|s,d|remove_filed,trueifforceFile.symlinks,dendend
Createssymbolic links.
Argumentssrc (a single path or an array of paths) anddest (a single path) should beinterpretable as paths.
Ifsrc is the path to an existing file:
When
destis the path to a non-existent file, creates a symbolic link atdestpointing tosrc:FileUtils.touch('src0.txt')File.exist?('dest0.txt')# => falseFileUtils.ln_s('src0.txt','dest0.txt')File.symlink?('dest0.txt')# => true
When
destis the path to an existing file, creates a symbolic link atdestpointing tosrcif and only if keyword argumentforce: trueis 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')# => trueFileUtils.ln_s('src1.txt','dest1.txt')# Raises Errno::EEXIST.
Ifdest is the path to a directory, creates a symbolic link atdest/src pointing tosrc:
FileUtils.touch('src2.txt')FileUtils.mkdir('destdir2')FileUtils.ln_s('src2.txt','destdir2')File.symlink?('destdir2/src2.txt')# => true
Ifsrc is an array of paths to existing files anddest is a directory, for each childchild insrc creates a symbolic linkdest/child pointing tochild:
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')# => trueFile.symlink?('destdir3/src1.txt')# => true
Keyword arguments:
force: true- overwritesdestif 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.txtln -s src1.txt destdir1ln -sf src2.txt dest2.txtln -s srcdir3/src0.txt srcdir3/src1.txt destdir3
Related:FileUtils.ln_sf.
Source
# File lib/fileutils.rb, line 726defln_sf(src,dest,noop:nil,verbose:nil)ln_ssrc,dest,force:true,noop:noop,verbose:verboseend
LikeFileUtils.ln_s, but always with keyword argumentforce: true given.
Source
# File lib/fileutils.rb, line 733defln_sr(src,dest,target_directory:true,force:nil,noop:nil,verbose:nil)cmd ="ln -s#{force ? 'f' : ''}#{target_directory ? '' : 'T'}"ifverbosefu_each_src_dest0(src,dest,target_directory)do|s,d|iftarget_directoryparent =File.dirname(d)destdirs =fu_split_path(parent)real_ddirs =fu_split_path(File.realpath(parent))elsedestdirs||=fu_split_path(dest)real_ddirs||=fu_split_path(File.realdirpath(dest))endsrcdirs =fu_split_path(s)i =fu_common_components(srcdirs,destdirs)n =destdirs.size-in-=1unlesstarget_directorylink1 =fu_clean_components(*Array.new([n,0].max,'..'),*srcdirs[i..-1])beginreal_sdirs =fu_split_path(File.realdirpath(s))rescuenilrescueelsei =fu_common_components(real_sdirs,real_ddirs)n =real_ddirs.size-in-=1unlesstarget_directorylink2 =fu_clean_components(*Array.new([n,0].max,'..'),*real_sdirs[i..-1])link1 =link2iflink1.size>link2.sizeends =File.join(link1)fu_output_message [cmd,s,d].flatten.join(' ')ifverbosenextifnoopremove_filed,trueifforceFile.symlinks,dendend
LikeFileUtils.ln_s, but create links relative todest.
Source
# File lib/fileutils.rb, line 317defmkdir(list,mode:nil,noop:nil,verbose:nil)list =fu_list(list)fu_output_message"mkdir #{mode ? ('-m %03o ' % mode) : ''}#{list.join ' '}"ifverbosereturnifnooplist.eachdo|dir|fu_mkdirdir,modeendend
Creates directories at the paths in the givenlist (a single path or an array of paths); returnslist if it is an array,[list] otherwise.
Argumentlist or its elements should beinterpretable as paths.
With no keyword arguments, creates a directory at eachpath inlist by calling:Dir.mkdir(path, mode); seeDir.mkdir:
FileUtils.mkdir(%w[tmp0 tmp1])# => ["tmp0", "tmp1"]FileUtils.mkdir('tmp4')# => ["tmp4"]
Keyword arguments:
mode:mode- also callsFile.chmod(mode, path); seeFile.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 tmp1mkdir -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.
Source
# File lib/fileutils.rb, line 366defmkdir_p(list,mode:nil,noop:nil,verbose:nil)list =fu_list(list)fu_output_message"mkdir -p #{mode ? ('-m %03o ' % mode) : ''}#{list.join ' '}"ifverbosereturn*listifnooplist.eachdo|item|path =remove_trailing_slash(item)stack = []untilFile.directory?(path)||File.dirname(path)==pathstack.pushpathpath =File.dirname(path)endstack.reverse_eachdo|dir|beginfu_mkdirdir,moderescueSystemCallErrorraiseunlessFile.directory?(dir)endendendreturn*listend
Creates directories at the paths in the givenlist (a single path or an array of paths), also creating ancestor directories as needed; returnslist if it is an array,[list] otherwise.
Argumentlist or its elements should beinterpretable as paths.
With no keyword arguments, creates a directory at eachpath inlist, along with any needed ancestor directories, by calling:Dir.mkdir(path, mode); seeDir.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); seeFile.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 tmp1mkdir -p -m 700 tmp2 tmp3
Raises an exception if for any reason a directory cannot be created.
FileUtils.mkpath andFileUtils.makedirs are aliases forFileUtils.mkdir_p.
Related:FileUtils.mkdir.
Source
# File lib/fileutils.rb, line 1154defmv(src,dest,force:nil,noop:nil,verbose:nil,secure:nil)fu_output_message"mv#{force ? ' -f' : ''} #{[src,dest].flatten.join ' '}"ifverbosereturnifnoopfu_each_src_dest(src,dest)do|s,d|destent =Entry_.new(d,nil,true)beginifdestent.exist?ifdestent.directory?raiseErrno::EEXIST,dendendbeginFile.renames,drescueErrno::EXDEV,Errno::EPERM# move from unencrypted to encrypted dir (ext4)copy_entrys,d,trueifsecureremove_entry_secures,forceelseremove_entrys,forceendendrescueSystemCallErrorraiseunlessforceendendend
Moves entries.
Argumentssrc (a single path or an array of paths) anddest (a single path) should beinterpretable as paths.
Ifsrc anddest are on different file systems, first copies, then removessrc.
May cause a local vulnerability if not called with keyword argumentsecure: true; seeAvoiding the TOCTTOU Vulnerability.
Ifsrc is the path to a single file or directory anddest does not exist, movessrc todest:
tree('src0')# => src0# |-- src0.txt# `-- src1.txtFile.exist?('dest0')# => falseFileUtils.mv('src0','dest0')File.exist?('src0')# => falsetree('dest0')# => dest0# |-- src0.txt# `-- src1.txt
Ifsrc is an array of paths to files and directories anddest is the path to a directory, copies from each path in the array todest:
File.file?('src1.txt')# => truetree('src1')# => src1# |-- src.dat# `-- src.txtDir.empty?('dest1')# => trueFileUtils.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, ifsrcanddestare on different file systems), ignores raised exceptions ofStandardErrorand its descendants.noop: true- does not move files.secure: true- removessrcsecurely; see details atFileUtils.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:
mvsrc0dest0mvsrc1.txtsrc1dest1
Source
# File lib/fileutils.rb, line 198defpwdDir.pwdend
Returns a string containing the path to the current directory:
FileUtils.pwd# => "/rdoc/fileutils"
Related:FileUtils.cd.
Source
# File lib/fileutils.rb, line 1489defremove_dir(path,force =false)raiseErrno::ENOTDIR,pathunlessforceorFile.directory?(path)remove_entrypath,forceend
Recursively removes the directory entry given bypath, which should be the entry for a regular file, a symbolic link, or a directory.
Argumentpath should beinterpretable as a path.
Optional argumentforce specifies whether to ignore raised exceptions ofStandardError and its descendants.
Related:methods for deleting.
Source
# File lib/fileutils.rb, line 1446defremove_entry(path,force =false)Entry_.new(path).postorder_traversedo|ent|beginent.removerescueraiseunlessforceendendrescueraiseunlessforceend
Removes the entry given bypath, which should be the entry for a regular file, a symbolic link, or a directory.
Argumentpath should beinterpretable as a path.
Optional argumentforce specifies whether to ignore raised exceptions ofStandardError and its descendants.
Related:FileUtils.remove_entry_secure.
Source
# File lib/fileutils.rb, line 1348defremove_entry_secure(path,force =false)unlessfu_have_symlink?remove_entrypath,forcereturnendfullpath =File.expand_path(path)st =File.lstat(fullpath)unlessst.directory?File.unlinkfullpathreturnend# is a directory.parent_st =File.stat(File.dirname(fullpath))unlessparent_st.world_writable?remove_entrypath,forcereturnendunlessparent_st.sticky?raiseArgumentError,"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 rooteuid =Process.euiddot_file =fullpath+"/."beginFile.open(dot_file) {|f|unlessfu_stat_identical_entry?(st,f.stat)# symlink (TOC-to-TOU attack?)File.unlinkfullpathreturnendf.chowneuid,-1f.chmod0700 }rescueErrno::EISDIR# JRuby in non-native mode can't open files as dirsFile.lstat(dot_file).tap {|fstat|unlessfu_stat_identical_entry?(st,fstat)# symlink (TOC-to-TOU attack?)File.unlinkfullpathreturnendFile.chowneuid,-1,dot_fileFile.chmod0700,dot_file }endunlessfu_stat_identical_entry?(st,File.lstat(fullpath))# TOC-to-TOU attack?File.unlinkfullpathreturnend# ---- tree root is frozen ----root =Entry_.new(path)root.preorder_traversedo|ent|ifent.directory?ent.chowneuid,-1ent.chmod0700endendroot.postorder_traversedo|ent|beginent.removerescueraiseunlessforceendendrescueraiseunlessforceend
Securely removes the entry given bypath, which should be the entry for a regular file, a symbolic link, or a directory.
Argumentpath should beinterpretable as a path.
Avoids a local vulnerability that can exist in certain circumstances; seeAvoiding the TOCTTOU Vulnerability.
Optional argumentforce specifies whether to ignore raised exceptions ofStandardError and its descendants.
Related:methods for deleting.
Source
# File lib/fileutils.rb, line 1470defremove_file(path,force =false)Entry_.new(path).remove_filerescueraiseunlessforceend
Removes the file entry given bypath, which should be the entry for a regular file or a symbolic link.
Argumentpath should beinterpretable as a path.
Optional argumentforce specifies whether to ignore raised exceptions ofStandardError and its descendants.
Related:methods for deleting.
Source
# File lib/fileutils.rb, line 1213defrm(list,force:nil,noop:nil,verbose:nil)list =fu_list(list)fu_output_message"rm#{force ? ' -f' : ''} #{list.join ' '}"ifverbosereturnifnooplist.eachdo|path|remove_filepath,forceendend
Removes entries at the paths in the givenlist (a single path or an array of paths) returnslist, if it is an array,[list] otherwise.
Argumentlist or its elements should beinterpretable as paths.
With no keyword arguments, removes files at the paths given inlist:
FileUtils.touch(['src0.txt','src0.dat'])FileUtils.rm(['src0.dat','src0.txt'])# => ["src0.dat", "src0.txt"]
Keyword arguments:
force: true- ignores raised exceptions ofStandardErrorand 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:
rmsrc0.datsrc0.txt
Related:methods for deleting.
Source
# File lib/fileutils.rb, line 1238defrm_f(list,noop:nil,verbose:nil)rmlist,force:true,noop:noop,verbose:verboseend
Equivalent to:
FileUtils.rm(list,force:true,**kwargs)
Argumentlist (a single path or an array of paths) should beinterpretable as paths.
SeeFileUtils.rm for keyword arguments.
Related:methods for deleting.
Source
# File lib/fileutils.rb, line 1296defrm_r(list,force:nil,noop:nil,verbose:nil,secure:nil)list =fu_list(list)fu_output_message"rm -r#{force ? 'f' : ''} #{list.join ' '}"ifverbosereturnifnooplist.eachdo|path|ifsecureremove_entry_securepath,forceelseremove_entrypath,forceendendend
Removes entries at the paths in the givenlist (a single path or an array of paths); returnslist, if it is an array,[list] otherwise.
Argumentlist or its elements should beinterpretable as paths.
May cause a local vulnerability if not called with keyword argumentsecure: true; seeAvoiding 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')# => falseFile.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.txtFileUtils.rm_r('src1')File.exist?('src1')# => false
Keyword arguments:
force: true- ignores raised exceptions ofStandardErrorand its descendants.noop: true- does not remove entries; returnsnil.secure: true- removessrcsecurely; see details atFileUtils.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.txtrm -r src1
Related:methods for deleting.
Source
# File lib/fileutils.rb, line 1325defrm_rf(list,noop:nil,verbose:nil,secure:nil)rm_rlist,force:true,noop:noop,verbose:verbose,secure:secureend
Equivalent to:
FileUtils.rm_r(list,force:true,**kwargs)
Argumentlist or its elements should beinterpretable as paths.
May cause a local vulnerability if not called with keyword argumentsecure: true; seeAvoiding the TOCTTOU Vulnerability.
SeeFileUtils.rm_r for keyword arguments.
Related:methods for deleting.
Source
# File lib/fileutils.rb, line 443defrmdir(list,parents:nil,noop:nil,verbose:nil)list =fu_list(list)fu_output_message"rmdir #{parents ? '-p ' : ''}#{list.join ' '}"ifverbosereturnifnooplist.eachdo|dir|Dir.rmdir(dir =remove_trailing_slash(dir))ifparentsbeginuntil (parent =File.dirname(dir))=='.'orparent==dirdir =parentDir.rmdir(dir)endrescueErrno::ENOTEMPTY,Errno::EEXIST,Errno::ENOENTendendendend
Removes directories at the paths in the givenlist (a single path or an array of paths); returnslist, if it is an array,[list] otherwise.
Argumentlist or its elements should beinterpretable as paths.
With no keyword arguments, removes the directory at eachpath inlist, by calling:Dir.rmdir(path); seeDir.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/tmp3rmdir -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.
Source
# File lib/fileutils.rb, line 2004deftouch(list,noop:nil,verbose:nil,mtime:nil,nocreate:nil)list =fu_list(list)t =mtimeifverbosefu_output_message"touch #{nocreate ? '-c ' : ''}#{t ? t.strftime('-t %Y%m%d%H%M.%S ') : ''}#{list.join ' '}"endreturnifnooplist.eachdo|path|created =nocreatebeginFile.utime(t,t,path)rescueErrno::ENOENTraiseifcreatedFile.open(path,'a') { ; }created =trueretryiftendendend
Updates modification times (mtime) and access times (atime) of the entries given by the paths inlist (a single path or an array of paths); returnslist if it is an array,[list] otherwise.
By default, creates an empty file for any path to a non-existent entry; use keyword argumentnocreate to raise an exception instead.
Argumentlist or its elements should beinterpretable as paths.
Examples:
# Single path.f =File.new('src0.txt')# Existing file.f.atime# => 2022-06-10 11:11:21.200277 -0700f.mtime# => 2022-06-10 11:11:21.200277 -0700FileUtils.touch('src0.txt')f =File.new('src0.txt')f.atime# => 2022-06-11 08:28:09.8185343 -0700f.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:
touchsrc0.txttouchsrc0.txtsrc0.dattouchsrc0.txt
Related:FileUtils.uptodate?.
Source
# File lib/fileutils.rb, line 265defuptodate?(new,old_list)returnfalseunlessFile.exist?(new)new_time =File.mtime(new)old_list.eachdo|old|ifFile.exist?(old)returnfalseunlessnew_time>File.mtime(old)endendtrueend
Returnstrue if the file at pathnew is newer than all the files at paths in arrayold_list;false otherwise.
Argumentnew and the elements ofold_list should beinterpretable as paths:
FileUtils.uptodate?('Rakefile', ['Gemfile','README.md'])# => trueFileUtils.uptodate?('Gemfile', ['Rakefile','README.md'])# => false
A non-existent file is considered to be infinitely old.
Related:FileUtils.touch.