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
Returns the current working directory.
Returns the current working directory.
Returns the current working directory.
Returns the current working directory.
Returns the command search path in an array
Returns the umask
Public Class Methods
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 392 def Shell.alias_command(ali, command, *opts, &block) CommandProcessor.alias_command(ali, command, *opts, &block) end
Creates a new Shell
instance with the current working directory set to path
.
# File lib/shell.rb, line 125 def cd(path) new(path) end
# File lib/shell.rb, line 114 def debug=(val) @debug = val @verbose = val if val end
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 372 def Shell.def_system_command(command, path = command) CommandProcessor.def_system_command(command, path) end
# File lib/shell.rb, line 158 def default_record_separator if @default_record_separator @default_record_separator else $/ end end
# File lib/shell.rb, line 166 def default_record_separator=(rs) @default_record_separator = rs end
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 142 def default_system_path if @default_system_path @default_system_path else ENV["PATH"].split(":") end end
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 154 def default_system_path=(path) @default_system_path = path end
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 412 def Shell.install_system_commands(pre = "sys_") CommandProcessor.install_system_commands(pre) end
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 183 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
# File lib/shell.rb, line 425 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
Convenience method for Shell::CommandProcessor.unalias_command
# File lib/shell.rb, line 397 def Shell.unalias_command(ali) CommandProcessor.unalias_command(ali) end
Convenience method for Shell::CommandProcessor.undef_system_command
# File lib/shell.rb, line 377 def Shell.undef_system_command(command) CommandProcessor.undef_system_command(command) end
Public Instance Methods
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 260 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
# File lib/shell.rb, line 215 def debug=(val) @debug = val @verbose = val if val end
# File lib/shell.rb, line 226 def expand_path(path) File.expand_path(path, @cwd) end
Object#inspect
# File lib/shell.rb, line 417 def inspect if debug.kind_of?(Integer) && debug > 2 super else to_s end end
Returns a list of scheduled jobs.
# File lib/shell.rb, line 344 def jobs @process_controller.jobs end
Sends the given signal
to the given job
# File lib/shell.rb, line 352 def kill(sig, command) @process_controller.kill_job(sig, command) end
Pops a directory from the directory stack, and sets the current directory to it.
# File lib/shell.rb, line 328 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
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 294 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
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 204 def system_path=(path) @system_path = path rehash end