Module: Maid::Tools
- Includes:
- Deprecated
- Defined in:
- lib/maid/tools.rb
Overview
These "tools" are methods available in the Maid DSL.
In general, methods are expected to:
- Automatically expand paths (that is,
'~/Downloads/foo.zip'becomes'/home/username/Downloads/foo.zip') - Respect the
noop(dry-run) option if it is set
Some methods are not available on all platforms. An ArgumentError is raised when a command is not available. See
tags such as: [Mac OS X]
Instance Method Summary (collapse)
-
- (Object) accessed_at(path)
Get the time that a file was last accessed.
-
- (Object) created_at(path)
Get the creation time of a file.
-
- (Object) dir(globs)
Give all files matching the given glob.
-
- (Object) disk_usage(path)
Calculate disk usage of a given path in kilobytes.
-
- (Object) downloaded_from(path)
[Mac OS X] Use Spotlight metadata to determine the site from which a file was downloaded.
-
- (Object) duration_s(path)
[Mac OS X] Use Spotlight metadata to determine audio length.
-
- (Object) find(path, &block)
Find matching files, akin to the Unix utility
find. - - (Object) git_piston(path) deprecated Deprecated.
- - (Object) last_accessed(path) deprecated Deprecated.
-
- (Object) locate(name)
[Mac OS X] Use Spotlight to locate all files matching the given filename.
-
- (Object) mkdir(path, options = {})
Create a directory and all of its parent directories.
-
- (Object) modified_at(path)
Get the modification time of a file.
-
- (Object) move(sources, destination)
Move
sourcesto adestinationdirectory. -
- (Object) remove(paths, options = {})
Delete the files at the given path recursively.
-
- (Object) rename(source, destination)
Rename a single file.
-
- (Object) sync(from, to, options = {})
Simple sync two files/folders using
rsync. -
- (Object) trash(paths, options = {})
Move the given paths to the user's trash.
-
- (Object) zipfile_contents(path)
List the contents of a zip file.
Instance Method Details
- (Object) accessed_at(path)
Get the time that a file was last accessed.
In Unix speak, atime.
Examples
accessed_at('foo.zip') # => Sat Apr 09 10:50:01 -0400 2011
349 350 351 |
# File 'lib/maid/tools.rb', line 349 def accessed_at(path) File.atime((path)) end |
- (Object) created_at(path)
Get the creation time of a file.
In Unix speak, ctime.
Examples
created_at('foo.zip') # => Sat Apr 09 10:50:01 -0400 2011
338 339 340 |
# File 'lib/maid/tools.rb', line 338 def created_at(path) File.ctime((path)) end |
- (Object) dir(globs)
Give all files matching the given glob.
Note that the globs are not regexps (they're closer to shell globs). However, some regexp-like notation can be
used, e.g. ?, [a-z], {tgz,zip}. For more details, see Ruby's documentation on Dir.glob.
The matches are sorted lexically to aid in readability when using --dry-run.
Examples
Single glob:
dir('~/Downloads/*.zip')
Specifying multiple extensions succinctly:
dir('~/Downloads/*.{exe,deb,dmg,pkg,rpm}')
Multiple glob (all are equivalent):
dir(['~/Downloads/*.zip', '~/Dropbox/*.zip'])
dir(%w(~/Downloads/*.zip ~/Dropbox/*.zip))
dir('~/{Downloads,Dropbox}/*.zip')
Recursing into subdirectories (see also: find):
dir('~/Music/**/*.m4a')
204 205 206 207 208 209 |
# File 'lib/maid/tools.rb', line 204 def dir(globs) (globs). map { |glob| Dir.glob(glob) }. flatten. sort end |
- (Object) disk_usage(path)
Calculate disk usage of a given path in kilobytes.
See also: Maid::NumericExtensions::SizeToKb.
Examples
disk_usage('foo.zip') # => 136
319 320 321 322 323 324 325 326 327 328 329 |
# File 'lib/maid/tools.rb', line 319 def disk_usage(path) raw = cmd("du -s #{ sh_escape(path) }") # FIXME: This reports in kilobytes, but should probably report in bytes. usage_kb = raw.split(/\s+/).first.to_i if usage_kb.zero? raise "Stopping pessimistically because of unexpected value from du (#{ raw.inspect })" else usage_kb end end |
- (Object) downloaded_from(path)
[Mac OS X] Use Spotlight metadata to determine the site from which a file was downloaded.
Examples
downloaded_from('foo.zip') # => ['http://www.site.com/foo.zip', 'http://www.site.com/']
287 288 289 290 291 |
# File 'lib/maid/tools.rb', line 287 def downloaded_from(path) raw = cmd("mdls -raw -name kMDItemWhereFroms #{ sh_escape(path) }") clean = raw[1, raw.length - 2] clean.split(/,\s+/).map { |s| t = s.strip; t[1, t.length - 2] } end |
- (Object) duration_s(path)
[Mac OS X] Use Spotlight metadata to determine audio length.
Examples
duration_s('foo.mp3') # => 235.705
298 299 300 |
# File 'lib/maid/tools.rb', line 298 def duration_s(path) cmd("mdls -raw -name kMDItemDurationSeconds #{ sh_escape(path) }").to_f end |
- (Object) find(path, &block)
Find matching files, akin to the Unix utility find.
If no block is given, it will return an array. Otherwise, it acts like Find.find.
Examples
Without a block:
find('~/Downloads/') # => [...]
Recursing and filtering using a regular expression:
find('~/Downloads/').grep(/\.pdf$/)
(Note: It's just Ruby, so any methods in Array and Enumerable can be used.)
Recursing with a block:
find('~/Downloads/') do |path|
# ...
end
259 260 261 262 263 264 265 266 267 268 269 |
# File 'lib/maid/tools.rb', line 259 def find(path, &block) = (path) if block.nil? files = [] Find.find() { |file_path| files << file_path } files else Find.find(, &block) end end |
- (Object) git_piston(path)
Pull and push the git repository at the given path.
Since this is deprecated, you might also be interested in SparkleShare, a great
git-based file syncronization project.
Examples
git_piston('~/code/projectname')
383 384 385 386 387 |
# File 'lib/maid/tools.rb', line 383 def git_piston(path) full_path = (path) stdout = cmd("cd #{ sh_escape(full_path) } && git pull && git push 2>&1") log("Fired git piston on #{ sh_escape(full_path) }. STDOUT:\n\n#{ stdout }") end |
- (Object) last_accessed(path)
Alias of accessed_at.
356 357 358 359 |
# File 'lib/maid/tools.rb', line 356 def last_accessed(path) # Not a normal `alias` so the deprecation notice shows in the docs. accessed_at(path) end |
- (Object) locate(name)
[Mac OS X] Use Spotlight to locate all files matching the given filename.
[Ubuntu] Not currently supported. See issue #67.
Examples
locate('foo.zip') # => ['/a/foo.zip', '/b/foo.zip']
278 279 280 |
# File 'lib/maid/tools.rb', line 278 def locate(name) cmd("mdfind -name #{ sh_escape(name) }").split("\n") end |
- (Object) mkdir(path, options = {})
Create a directory and all of its parent directories.
The path of the created directory is returned, which allows for chaining (see examples).
Options
:mode
The symbolic and absolute mode can both be used, for example: 0700, 'u=wr,go=rr'
Examples
Creating a directory with a specific mode:
mkdir('~/Music/Pink Floyd/', :mode => 0644)
Ensuring a directory exists when moving:
move('~/Downloads/Pink Floyd*.mp3', mkdir('~/Music/Pink Floyd/'))
230 231 232 233 234 235 |
# File 'lib/maid/tools.rb', line 230 def mkdir(path, = {}) path = (path) log("mkdir -p #{ sh_escape(path) }") FileUtils.mkdir_p(path, @file_options.merge()) path end |
- (Object) modified_at(path)
Get the modification time of a file.
In Unix speak, mtime.
Examples
modified_at('foo.zip') # => Sat Apr 09 10:50:01 -0400 2011
369 370 371 |
# File 'lib/maid/tools.rb', line 369 def modified_at(path) File.mtime((path)) end |
- (Object) move(sources, destination)
Move sources to a destination directory.
Movement is only allowed to directories that already exist. If your intention is to rename, see the rename method.
Examples
Single path:
move('~/Downloads/foo.zip', '~/Archive/Software/Mac OS X/')
Multiple paths:
move(['~/Downloads/foo.zip', '~/Downloads/bar.zip'], '~/Archive/Software/Mac OS X/')
move(dir('~/Downloads/*.zip'), '~/Archive/Software/Mac OS X/')
32 33 34 35 36 37 38 39 40 41 42 43 44 |
# File 'lib/maid/tools.rb', line 32 def move(sources, destination) destination = (destination) if File.directory?(destination) (sources).each do |source| log("move #{ sh_escape(source) } #{ sh_escape(destination) }") FileUtils.mv(source, destination, @file_options) end else # Unix `mv` warns about the target not being a directory with multiple sources. Maid checks the same. warn("skipping move because #{ sh_escape(destination) } is not a directory (use 'mkdir' to create first, or use 'rename')") end end |
- (Object) remove(paths, options = {})
Delete the files at the given path recursively.
NOTE: In most cases, trash is a safer choice, since the files will be recoverable by retreiving them from the trash. Once you delete a file using remove, it's gone! Please use trash whenever possible and only use remove when necessary.
Options
:force => boolean
Force deletion (no error is raised if the file does not exist).
:secure => boolean
Infrequently needed. See FileUtils.remove_entry_secure
Examples
Single path:
remove('~/Downloads/foo.zip')
Multiple path:
remove(['~/Downloads/foo.zip', '~/Downloads/bar.zip'])
remove(dir('~/Downloads/*.zip'))
168 169 170 171 172 173 174 175 |
# File 'lib/maid/tools.rb', line 168 def remove(paths, = {}) (paths).each do |path| = @file_options.merge() log("Removing #{ sh_escape(path) }") FileUtils.rm_r(path, ) end end |
- (Object) rename(source, destination)
Rename a single file.
Any directories needed in order to complete the rename are made automatically.
Overwriting is not allowed; it logs a warning. If overwriting is desired, use remove to delete the file first, then use rename.
Examples
Simple rename:
rename('foo.zip', 'baz.zip') # "foo.zip" becomes "baz.zip"
Rename needing directories:
rename('foo.zip', 'bar/baz.zip') # "bar" is created, "foo.zip" becomes "baz.zip" within "bar"
Attempting to overwrite:
rename('foo.zip', 'existing.zip') # "skipping move of..."
65 66 67 68 69 70 71 72 73 74 75 76 77 |
# File 'lib/maid/tools.rb', line 65 def rename(source, destination) source = (source) destination = (destination) mkdir(File.dirname(destination)) if File.exist?(destination) warn("skipping rename of #{ sh_escape(source) } to #{ sh_escape(destination) } because it would overwrite") else log("rename #{ sh_escape(source) } #{ sh_escape(destination) }") FileUtils.mv(source, destination, @file_options) end end |
- (Object) sync(from, to, options = {})
Simple sync two files/folders using rsync.
The host OS must provide rsync. See the rsync man page for a detailed description.
man rsync
Options
:delete => boolean
:verbose => boolean
:archive => boolean (default true)
:update => boolean (default true)
:exclude => string
:prune_empty => boolean
Examples
Syncing a directory to a backup:
sync('~/music', '/backup/music')
Excluding a path:
sync('~/code', '/backup/code', :exclude => '.git')
Excluding multiple paths:
sync('~/code', '/backup/code', :exclude => ['.git', '.rvmrc'])
419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 |
# File 'lib/maid/tools.rb', line 419 def sync(from, to, = {}) # expand removes trailing slash # cannot use str[-1] due to ruby 1.8.7 restriction from = (from) + (from.end_with?('/') ? '/' : '') to = (to) + (to.end_with?('/') ? '/' : '') # default options = { :archive => true, :update => true }.merge() ops = [] ops << '-a' if [:archive] ops << '-v' if [:verbose] ops << '-u' if [:update] ops << '-m' if [:prune_empty] ops << '-n' if @file_options[:noop] Array([:exclude]).each do |path| ops << "--exclude=#{ sh_escape(path) }" end ops << '--delete' if [:delete] stdout = cmd("rsync #{ ops.join(' ') } #{ sh_escape(from) } #{ sh_escape(to) } 2>&1") log("Fired sync from #{ sh_escape(from) } to #{ sh_escape(to) }. STDOUT:\n\n#{ stdout }") end |
- (Object) trash(paths, options = {})
Move the given paths to the user's trash.
The path is still moved if a file already exists in the trash with the same name. However, the current date and time is appended to the filename.
Note: the OS-native "restore" or "put back" functionality for trashed files is not currently supported. (See issue #63.) However, they can be restored manually, and the Maid log can help assist with this.
Options
:remove_over => Fixnum (e.g. 1.gigabyte, 1024.megabytes)
Delete files over the given size rather than moving to the trash.
See also Maid::NumericExtensions::SizeToKb
Examples
Single path:
trash('~/Downloads/foo.zip')
Multiple paths:
trash(['~/Downloads/foo.zip', '~/Downloads/bar.zip'])
trash(dir('~/Downloads/*.zip'))
106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 |
# File 'lib/maid/tools.rb', line 106 def trash(paths, = {}) # ## Implementation Notes # # Trashing files correctly is surprisingly hard. What Maid ends up doing is one the easiest, most foolproof # solutions: moving the file. # # Unfortunately, that means it's not possile to restore files automatically in OSX or Ubuntu. The previous location # of the file is lost. # # OSX support depends on AppleScript or would require a not-yet-written C extension to interface with the OS. The # AppleScript solution is less than ideal: the user has to be logged in, Finder has to be running, and it makes the # "trash can sound" every time a file is moved. # # Ubuntu makes it easy to implement, and there's a Python library for doing so (see `trash-cli`). However, there's # not a Ruby equivalent yet. (paths).each do |path| target = File.join(@trash_path, File.basename(path)) safe_trash_path = File.join(@trash_path, "#{ File.basename(path) } #{ Time.now.strftime('%Y-%m-%d-%H-%M-%S') }") if [:remove_over] && File.exist?(path) && disk_usage(path) > [:remove_over] remove(path) end if File.exist?(path) if File.exist?(target) rename(path, safe_trash_path) else move(path, @trash_path) end end end end |
- (Object) zipfile_contents(path)
List the contents of a zip file.
Examples
zipfile_contents('foo.zip') # => ['foo/foo.exe', 'foo/README.txt']
307 308 309 310 |
# File 'lib/maid/tools.rb', line 307 def zipfile_contents(path) raw = cmd("unzip -Z1 #{ sh_escape(path) }") raw.split("\n") end |