Securely deleting files, while attempting to protect the user against obviously dangerous inputs As far as I can tell, no gem currently exists to wrap shred, the *nix utility to securely delete files.  I created a small class to do this, the key methods are:

def self.run cmd
  stdout,stderr,status = Open3.capture3 cmd
  raise "Failed executing #{cmd}: stdout: #{stdout}, stderr: #{stderr}, status #{status}" unless status.nil? || status == 0
  stdout
end

def self.validate_path path, required_regex=nil
  raise if required_regex &amp;&amp; !required_regex.is_a?(Regexp)
  File.expand_path(path).tap do |path|
    raise if path == '/'
    raise if required_regex &amp;&amp; !path.match(required_regex)
  end
end

def self.dir! path, opts={}
  return unless Dir.exist?(path)
  validate_path path, opts[:path_must_match]

  stdout = run "find #{path} -type f -exec #{shred_cmd} '{}' ';'"
  FileUtils.rm_rf path
  stdout
end



find is used to execute shred, since it lacks a recursive option.  I initially tried execdir instead of exec for security, but travis and other build environments hate it.  Potential problem?
validate_path tries to keep the user from screwing themselves by expanding the path, better ways of doing this?
Some notes:


def self.run cmd: Omiting parentheses on signatures is less and less idiomatic as time goes by, people have realized they are harder to read. I'd put them.
Open3.capture3 cmd: It's also less idiomatic than it was years ago to omit parentheses on calls (except for very specific DSL code).
stdout,stderr,status: Always a space after a comma.
def self.validate_path path, required_regex=nil. Positional optional arguments tend to get messy when you need to add new ones. I'd use always an options = {} hash. Ruby 2.0 has keyword arguments so this problem is fortunately gone.
raise if required_regex &amp;&amp; !required_regex.is_a?(Regexp). I wouldn't check the type of the variable, it's the caller's responsability to get it right.
File.expand_path(path).tap. This kind of tap usages are IMO cryptic and unnecessary.
Lots of raise ... if condition: Inline conditionals save some lines at the cost of making the branching logic harder to follow. I prefer writing full-fledged indentend conditionals (indentation is a powerful conveyor of information).
Open3.capture3 cmd. Running command from strings is dangerous (files with spaces anyone?), you should use some mechanism to escape them. 
find #{path} -type f. It's ok to call external commands when the the language is unable to do the task, but here you can easily perform a recursive find with, well, module find.


I'd write something like this:

require 'find'
require 'open3'
require 'fileutils'
require 'shellwords'

class SafeRemover
  def self.run(command_array)
    command_string = Shellwords.join(command_array)
    stdout, stderr, status = Open3.capture3(command_string)
    if !status || status == 0
      stdout
    else
      fail("Failed executing #{cmd}: stdout: #{stdout}, stderr: #{stderr}, status #{status}")
    end
  end

  def self.validate_path(path, options = {})
    required_regexp = options[:required_regexp]        
    path2 = File.expand_path(path)
    if !Dir.exist?(path2)
      fail("Directory does not exist: #{path2}")
    elsif path2 == "/"
      fail("You cannot delete /")
    elsif required_regexp &amp;&amp; !path2.match(required_regexp)
      fail("Path and required_regexp do not match")
    end
  end

  def self.dir!(root_directory, options = {})
    validate_path(root_directory, :required_regexp =&gt; options[:path_must_match])
    paths = Find.find(root_directory).select { |p| FileTest.file?(p) }
    output = paths.each_slice(100).map { |paths| run(["shred", *paths]) }.join
    FileUtils.rm_rf(root_directory)
    output
  end
end