Object
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.
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
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
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"
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 shell.rb, line 395 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 shell.rb, line 127 def cd(path) new(path) end
# File shell.rb, line 116 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 shell.rb, line 375 def Shell.def_system_command(command, path = command) CommandProcessor.def_system_command(command, path) end
# File shell.rb, line 160 def default_record_separator if @default_record_separator @default_record_separator else $/ end end
# File shell.rb, line 168 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 shell.rb, line 144 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 shell.rb, line 156 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 shell.rb, line 415 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 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
# File 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
Convenience method for Shell::CommandProcessor.unalias_command
# File shell.rb, line 400 def Shell.unalias_command(ali) CommandProcessor.unalias_command(ali) end
Convenience method for Shell::CommandProcessor.undef_system_command
# File shell.rb, line 380 def Shell.undef_system_command(command) CommandProcessor.undef_system_command(command) end
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 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
# File shell.rb, line 218 def debug=(val) @debug = val @verbose = val if val end
# File shell.rb, line 229 def expand_path(path) File.expand_path(path, @cwd) end
# File shell.rb, line 420 def inspect if debug.kind_of?(Integer) && debug > 2 super else to_s end end
Returns a list of scheduled jobs.
# File shell.rb, line 347 def jobs @process_controller.jobs end
Sends the given signal
to the given job
# File shell.rb, line 355 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 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
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 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
Sets the system path (the Shell
instance's PATH environment variable).
path
should be an array of directory name strings.
# File shell.rb, line 206 def system_path=(path) @system_path = path rehash end