# class Shell

`Shell` implements an idiomatic Ruby interface for common UNIX shell commands.

It provides users the ability to execute commands with filters and pipes, like `sh`/`csh` by using native facilities of Ruby.

## Examples¶ ↑

### Temp file creation¶ ↑

In this example we will create three `tmpFile`'s in three different folders under the `/tmp` directory.

    sh = Shell.cd("/tmp") # Change to the /tmp directory
    sh.mkdir "shell-test-1" unless sh.exists?("shell-test-1")
    # make the 'shell-test-1' directory if it doesn't already exist
    sh.cd("shell-test-1") # Change to the /tmp/shell-test-1 directory
    for dir in ["dir1", "dir3", "dir5"]
      if !sh.exists?(dir)
        sh.mkdir dir # make dir if it doesn't already exist
        sh.cd(dir) do
          # change to the `dir` directory
          f = sh.open("tmpFile", "w") # open a new file in write mode
          f.print "TEST\n"            # write to the file
          f.close                     # close the file handler
        end
        print sh.pwd                  # output the process working directory
      end
    end

### Temp file creation with self¶ ↑

This example is identical to the first, except we're using `CommandProcessor#transact`.

`CommandProcessor#transact` executes the given block against self, in this case `sh`; our `Shell` object. Within the block we can substitute `sh.cd` to `cd`, because the scope within the block uses `sh` already.

    sh = Shell.cd("/tmp")
    sh.transact do
      mkdir "shell-test-1" unless exists?("shell-test-1")
      cd("shell-test-1")
      for dir in ["dir1", "dir3", "dir5"]
        if !exists?(dir)
          mkdir dir
          cd(dir) do
            f = open("tmpFile", "w")
            f.print "TEST\n"
            f.close
          end
          print pwd
        end
      end
    end

### Pipe /etc/printcap into a file¶ ↑

In this example we will read the operating system file `/etc/printcap`, generated by `cupsd`, and then output it to a new file relative to the `pwd` of `sh`.

    sh = Shell.new
    sh.cat("/etc/printcap") | sh.tee("tee1") > "tee2"
    (sh.cat < "/etc/printcap") | sh.tee("tee11") > "tee12"
    sh.cat("/etc/printcap") | sh.tee("tee1") >> "tee2"
    (sh.cat < "/etc/printcap") | sh.tee("tee11") >> "tee12"

### Attributes

cascade[RW]
debug[R]
debug?[R]
verbose[RW]
verbose?[RW]
command_processor[R]
cwd[R]

Returns the current working directory.

debug[R]
debug?[R]
dir[R]

Returns the current working directory.

dir_stack[R]
dirs[R]
getwd[R]

Returns the current working directory.

process_controller[R]
pwd[R]

Returns the current working directory.

record_separator[RW]
system_path[R]

Returns the command search path in an array

umask[RW]

Returns the umask

verbose[RW]
verbose?[RW]

### Public Class Methods

alias_command(alias, command, *opts, &block) click to toggle source

Convenience method for `Shell::CommandProcessor.alias_command`. Defines an instance method which will execute a command under an alternative name.

    Shell.def_system_command('date')
    Shell.alias_command('date_in_utc', 'date', '-u')
    Shell.new.date_in_utc # => Sat Jan 25 16:59:57 UTC 2014

    # File lib/shell.rb, line 395
    def Shell.alias_command(ali, command, *opts, &block)
      CommandProcessor.alias_command(ali, command, *opts, &block)
    end

cd(path) click to toggle source

Creates a new `Shell` instance with the current working directory set to `path`.

    # File lib/shell.rb, line 127
    def cd(path)
      new(path)
    end

debug=(val) click to toggle source

    # File lib/shell.rb, line 116
    def debug=(val)
      @debug = val
      @verbose = val if val
    end

def_system_command(command, path = command) click to toggle source

Convenience method for `Shell::CommandProcessor.def_system_command`. Defines an instance method which will execute the given shell command. If the executable is not in `Shell.default_system_path`, you must supply the path to it.

    Shell.def_system_command('hostname')
    Shell.new.hostname # => localhost

    # How to use an executable that's not in the default path

    Shell.def_system_command('run_my_program', "~/hello")
    Shell.new.run_my_program # prints "Hello from a C program!"

    # File lib/shell.rb, line 375
    def Shell.def_system_command(command, path = command)
      CommandProcessor.def_system_command(command, path)
    end

default_record_separator() click to toggle source

    # File lib/shell.rb, line 160
    def default_record_separator
      if @default_record_separator
        @default_record_separator
      else
        $/
      end
    end

default_record_separator=(rs) click to toggle source

    # File lib/shell.rb, line 168
    def default_record_separator=(rs)
      @default_record_separator = rs
    end

default_system_path() click to toggle source

Returns the directories in the current shell's PATH environment variable as an array of directory names. This sets the `system_path` for all instances of `Shell`.

Example: If in your current shell, you did:

    $ echo $PATH
    /usr/bin:/bin:/usr/local/bin

Running this method in the above shell would then return:

    ["/usr/bin", "/bin", "/usr/local/bin"]

    # File lib/shell.rb, line 144
    def default_system_path
      if @default_system_path
        @default_system_path
      else
        ENV["PATH"].split(":")
      end
    end

default_system_path=(path) click to toggle source

Sets the `system_path` that new instances of `Shell` should have as their initial system_path.

`path` should be an array of directory name strings.

    # File lib/shell.rb, line 156
    def default_system_path=(path)
      @default_system_path = path
    end

install_system_commands(pre = "sys_") click to toggle source

Convenience method for Shell::CommandProcessor.install_system_commands. Defines instance methods representing all the executable files found in `Shell.default_system_path`, with the given prefix prepended to their names.

    Shell.install_system_commands
    Shell.new.sys_echo("hello") # => hello

    # File lib/shell.rb, line 415
    def Shell.install_system_commands(pre = "sys_")
      CommandProcessor.install_system_commands(pre)
    end

new(pwd, umask) → obj click to toggle source

Creates a `Shell` object which current directory is set to the process current directory, unless otherwise specified by the `pwd` argument.

    # File lib/shell.rb, line 185
    def initialize(pwd = Dir.pwd, umask = nil)
      @cwd = File.expand_path(pwd)
      @dir_stack = []
      @umask = umask

      @system_path = Shell.default_system_path
      @record_separator = Shell.default_record_separator

      @command_processor = CommandProcessor.new(self)
      @process_controller = ProcessController.new(self)

      @verbose = Shell.verbose
      @debug = Shell.debug
    end

notify(*opts) { |mes| ... } click to toggle source

    # File lib/shell.rb, line 428
    def self.notify(*opts)
      Shell::debug_output_synchronize do
        if opts[-1].kind_of?(String)
          yorn = verbose?
        else
          yorn = opts.pop
        end
        return unless yorn

        if @debug_display_thread_id
          if @debug_display_process_id
            prefix = "shell(##{Process.pid}:#{Thread.current.to_s.sub("Thread", "Th")}): "
          else
            prefix = "shell(#{Thread.current.to_s.sub("Thread", "Th")}): "
          end
        else
          prefix = "shell: "
        end
        _head = true
        STDERR.print opts.collect{|mes|
          mes = mes.dup
          yield mes if iterator?
          if _head
            _head = false
            prefix + mes
          else
            " "* prefix.size + mes
          end
        }.join("\n")+"\n"
      end
    end

unalias_command(ali) click to toggle source

Convenience method for `Shell::CommandProcessor.unalias_command`

    # File lib/shell.rb, line 400
    def Shell.unalias_command(ali)
      CommandProcessor.unalias_command(ali)
    end

undef_system_command(command) click to toggle source

Convenience method for `Shell::CommandProcessor.undef_system_command`

    # File lib/shell.rb, line 380
    def Shell.undef_system_command(command)
      CommandProcessor.undef_system_command(command)
    end

### Public Instance Methods

cd(path = nil, verbose = @verbose)
Alias for: chdir
chdir(path) click to toggle source

Creates a `Shell` object which current directory is set to `path`.

If a block is given, it restores the current directory when the block ends.

If called as iterator, it restores the current directory when the block ends.

    # File lib/shell.rb, line 263
    def chdir(path = nil, verbose = @verbose)
      check_point

      if iterator?
        notify("chdir(with block) #{path}") if verbose
        cwd_old = @cwd
        begin
          chdir(path, nil)
          yield
        ensure
          chdir(cwd_old, nil)
        end
      else
        notify("chdir #{path}") if verbose
        path = "~" unless path
        @cwd = expand_path(path)
        notify "current dir: #{@cwd}"
        rehash
        Void.new(self)
      end
    end

Also aliased as: cd
debug=(val) click to toggle source

    # File lib/shell.rb, line 218
    def debug=(val)
      @debug = val
      @verbose = val if val
    end

expand_path(path) click to toggle source

    # File lib/shell.rb, line 229
    def expand_path(path)
      File.expand_path(path, @cwd)
    end

inspect() click to toggle source
Calls superclass method `Object#inspect`

    # File lib/shell.rb, line 420
    def inspect
      if debug.kind_of?(Integer) && debug > 2
        super
      else
        to_s
      end
    end

jobs() click to toggle source

Returns a list of scheduled jobs.

    # File lib/shell.rb, line 347
    def jobs
      @process_controller.jobs
    end

kill(signal, job) click to toggle source

Sends the given `signal` to the given `job`

    # File lib/shell.rb, line 355
    def kill(sig, command)
      @process_controller.kill_job(sig, command)
    end

popd()
Alias for: popdir
popdir() click to toggle source

Pops a directory from the directory stack, and sets the current directory to it.

    # File lib/shell.rb, line 331
    def popdir
      check_point

      notify("popdir")
      if pop = @dir_stack.pop
        chdir pop
        notify "dir stack: [#{@dir_stack.join ', '}]"
        self
      else
        Shell.Fail DirStackEmpty
      end
      Void.new(self)
    end

Also aliased as: popd
pushd(path = nil, verbose = @verbose)
Alias for: pushdir
pushdir(path) click to toggle source
pushdir(path) { &block }

Pushes the current directory to the directory stack, changing the current directory to `path`.

If `path` is omitted, it exchanges its current directory and the top of its directory stack.

If a block is given, it restores the current directory when the block ends.

    # File lib/shell.rb, line 297
    def pushdir(path = nil, verbose = @verbose)
      check_point

      if iterator?
        notify("pushdir(with block) #{path}") if verbose
        pushdir(path, nil)
        begin
          yield
        ensure
          popdir
        end
      elsif path
        notify("pushdir #{path}") if verbose
        @dir_stack.push @cwd
        chdir(path, nil)
        notify "dir stack: [#{@dir_stack.join ', '}]"
        self
      else
        notify("pushdir") if verbose
        if pop = @dir_stack.pop
          @dir_stack.push @cwd
          chdir pop
          notify "dir stack: [#{@dir_stack.join ', '}]"
          self
        else
          Shell.Fail DirStackEmpty
        end
      end
      Void.new(self)
    end

Also aliased as: pushd
system_path=(path) click to toggle source

Sets the system path (the `Shell` instance's PATH environment variable).

`path` should be an array of directory name strings.

    # File lib/shell.rb, line 206
    def system_path=(path)
      @system_path = path
      rehash
    end