/tools/Ruby/lib/ruby/1.8/ftools.rb

http://github.com/agross/netopenspace · Ruby · 261 lines · 145 code · 28 blank · 88 comment · 32 complexity · 48354c76b5350cd539146263ec6d320a MD5 · raw file

  1. #
  2. # = ftools.rb: Extra tools for the File class
  3. #
  4. # Author:: WATANABE, Hirofumi
  5. # Documentation:: Zachary Landau
  6. #
  7. # This library can be distributed under the terms of the Ruby license.
  8. # You can freely distribute/modify this library.
  9. #
  10. # It is included in the Ruby standard library.
  11. #
  12. # == Description
  13. #
  14. # ftools adds several (class, not instance) methods to the File class, for
  15. # copying, moving, deleting, installing, and comparing files, as well as
  16. # creating a directory path. See the File class for details.
  17. #
  18. # FileUtils contains all or nearly all the same functionality and more, and
  19. # is a recommended option over ftools
  20. #
  21. # When you
  22. #
  23. # require 'ftools'
  24. #
  25. # then the File class aquires some utility methods for copying, moving, and
  26. # deleting files, and more.
  27. #
  28. # See the method descriptions below, and consider using FileUtils as it is
  29. # more comprehensive.
  30. #
  31. class File
  32. end
  33. class << File
  34. BUFSIZE = 8 * 1024
  35. #
  36. # If +to+ is a valid directory, +from+ will be appended to +to+, adding
  37. # and escaping backslashes as necessary. Otherwise, +to+ will be returned.
  38. # Useful for appending +from+ to +to+ only if the filename was not specified
  39. # in +to+.
  40. #
  41. def catname(from, to)
  42. if directory? to
  43. join to.sub(%r([/\\]$), ''), basename(from)
  44. else
  45. to
  46. end
  47. end
  48. #
  49. # Copies a file +from+ to +to+. If +to+ is a directory, copies +from+
  50. # to <tt>to/from</tt>.
  51. #
  52. def syscopy(from, to)
  53. to = catname(from, to)
  54. fmode = stat(from).mode
  55. tpath = to
  56. not_exist = !exist?(tpath)
  57. from = open(from, "rb")
  58. to = open(to, "wb")
  59. begin
  60. while true
  61. to.syswrite from.sysread(BUFSIZE)
  62. end
  63. rescue EOFError
  64. ret = true
  65. rescue
  66. ret = false
  67. ensure
  68. to.close
  69. from.close
  70. end
  71. chmod(fmode, tpath) if not_exist
  72. ret
  73. end
  74. #
  75. # Copies a file +from+ to +to+ using #syscopy. If +to+ is a directory,
  76. # copies +from+ to <tt>to/from</tt>. If +verbose+ is true, <tt>from -> to</tt>
  77. # is printed.
  78. #
  79. def copy(from, to, verbose = false)
  80. $stderr.print from, " -> ", catname(from, to), "\n" if verbose
  81. syscopy from, to
  82. end
  83. alias cp copy
  84. #
  85. # Moves a file +from+ to +to+ using #syscopy. If +to+ is a directory,
  86. # copies from +from+ to <tt>to/from</tt>. If +verbose+ is true, <tt>from ->
  87. # to</tt> is printed.
  88. #
  89. def move(from, to, verbose = false)
  90. to = catname(from, to)
  91. $stderr.print from, " -> ", to, "\n" if verbose
  92. if RUBY_PLATFORM =~ /djgpp|(cyg|ms|bcc)win|mingw/ and file? to
  93. unlink to
  94. end
  95. fstat = stat(from)
  96. begin
  97. rename from, to
  98. rescue
  99. begin
  100. symlink readlink(from), to and unlink from
  101. rescue
  102. from_stat = stat(from)
  103. syscopy from, to and unlink from
  104. utime(from_stat.atime, from_stat.mtime, to)
  105. begin
  106. chown(fstat.uid, fstat.gid, to)
  107. rescue
  108. end
  109. end
  110. end
  111. end
  112. alias mv move
  113. #
  114. # Returns +true+ if and only if the contents of files +from+ and +to+ are
  115. # identical. If +verbose+ is +true+, <tt>from <=> to</tt> is printed.
  116. #
  117. def compare(from, to, verbose = false)
  118. $stderr.print from, " <=> ", to, "\n" if verbose
  119. return false if stat(from).size != stat(to).size
  120. from = open(from, "rb")
  121. to = open(to, "rb")
  122. ret = false
  123. fr = tr = ''
  124. begin
  125. while fr == tr
  126. fr = from.read(BUFSIZE)
  127. if fr
  128. tr = to.read(fr.size)
  129. else
  130. ret = to.read(BUFSIZE)
  131. ret = !ret || ret.length == 0
  132. break
  133. end
  134. end
  135. rescue
  136. ret = false
  137. ensure
  138. to.close
  139. from.close
  140. end
  141. ret
  142. end
  143. alias cmp compare
  144. #
  145. # Removes a list of files. Each parameter should be the name of the file to
  146. # delete. If the last parameter isn't a String, verbose mode will be enabled.
  147. # Returns the number of files deleted.
  148. #
  149. def safe_unlink(*files)
  150. verbose = if files[-1].is_a? String then false else files.pop end
  151. files.each do |file|
  152. begin
  153. unlink file
  154. $stderr.print "removing ", file, "\n" if verbose
  155. rescue Errno::EACCES # for Windows
  156. continue if symlink? file
  157. begin
  158. mode = stat(file).mode
  159. o_chmod mode | 0200, file
  160. unlink file
  161. $stderr.print "removing ", file, "\n" if verbose
  162. rescue
  163. o_chmod mode, file rescue nil
  164. end
  165. rescue
  166. end
  167. end
  168. end
  169. alias rm_f safe_unlink
  170. #
  171. # Creates a directory and all its parent directories.
  172. # For example,
  173. #
  174. # File.makedirs '/usr/lib/ruby'
  175. #
  176. # causes the following directories to be made, if they do not exist.
  177. # * /usr
  178. # * /usr/lib
  179. # * /usr/lib/ruby
  180. #
  181. # You can pass several directories, each as a parameter. If the last
  182. # parameter isn't a String, verbose mode will be enabled.
  183. #
  184. def makedirs(*dirs)
  185. verbose = if dirs[-1].is_a? String then false else dirs.pop end
  186. mode = 0755
  187. for dir in dirs
  188. parent = dirname(dir)
  189. next if parent == dir or directory? dir
  190. makedirs parent unless directory? parent
  191. $stderr.print "mkdir ", dir, "\n" if verbose
  192. if basename(dir) != ""
  193. begin
  194. Dir.mkdir dir, mode
  195. rescue SystemCallError
  196. raise unless directory? dir
  197. end
  198. end
  199. end
  200. end
  201. alias mkpath makedirs
  202. alias o_chmod chmod
  203. vsave, $VERBOSE = $VERBOSE, false
  204. #
  205. # Changes permission bits on +files+ to the bit pattern represented
  206. # by +mode+. If the last parameter isn't a String, verbose mode will
  207. # be enabled.
  208. #
  209. # File.chmod 0755, 'somecommand'
  210. # File.chmod 0644, 'my.rb', 'your.rb', true
  211. #
  212. def chmod(mode, *files)
  213. verbose = if files[-1].is_a? String then false else files.pop end
  214. $stderr.printf "chmod %04o %s\n", mode, files.join(" ") if verbose
  215. o_chmod mode, *files
  216. end
  217. $VERBOSE = vsave
  218. #
  219. # If +src+ is not the same as +dest+, copies it and changes the permission
  220. # mode to +mode+. If +dest+ is a directory, destination is <tt>dest/src</tt>.
  221. # If +mode+ is not set, default is used. If +verbose+ is set to true, the
  222. # name of each file copied will be printed.
  223. #
  224. def install(from, to, mode = nil, verbose = false)
  225. to = catname(from, to)
  226. unless exist? to and cmp from, to
  227. safe_unlink to if exist? to
  228. cp from, to, verbose
  229. chmod mode, to, verbose if mode
  230. end
  231. end
  232. end
  233. # vi:set sw=2: