The Shell Library


Ruby Way
By Hal Fulton
Slots : 1.0
Table of Contents

Ruby isn't necessarily convenient to use as a scripting language in every situation. For example, a Kornshell script can execute external programs simply by naming them, with no extraneous syntax.

The power and flexibility of Ruby has given it a more complex syntax than the average shell language. Additionally its functionality is segmented into different classes, modules, and libraries.

This situation motivated the creation of the Shell library. This library makes it easier to do things, such as connecting commands with pipes and redirecting output to files. It also consolidates functionality from several different sources so that they are transparently accessible from a Shell object.

Using Shell for I/O Redirection

The Shell class has two methods, new and cd, for instantiating a new object. The former creates a shell object associated with the current directory; the latter creates a shell object whose working directory will be the one specified.


 require "shell" sh1 =             # Work in the current directory sh2 ="/tmp/hal")  # Work in /tmp/hal 

The Shell library defines a few built-in commands as methods, such as echo, cat, and tee. These always return objects of class Filter (as do the user-defined commands that we'll look at shortly).

The nice thing about a Filter is that it understands I/O redirection. The methods (or operators) <, >, and | are defined so that they behave more or less as we expect from long experience with shell scripts.

If a redirection method has a string as a parameter, that string is taken to be the name of a file. If it has an IO object as a parameter, that object is used for the input or output operation. Here are some small examples:


 sh = # Print the motd file to stdout"/etc/motd") > STDOUT # Print it again  ( < "/etc/motd") > STDOUT  (sh.echo "This is a test") > "myfile.txt" # Append a line to /etc/motd sh.echo("Hello, world!") >> "/etc/motd" # Cat two files to stdout, tee-ing to a third ( "file1" "file2") | (tee "file3") > STDOUT 

Note that the > binds tightly. The parentheses that you see in the preceding code are necessary in most cases. Here are two correct usages and one incorrect one:


 # Ruby parser understands this..."myfile.txt") > STDOUT # ...and this also.  ( "myfile.txt") > STDOUT # TypeError! (a precedence problem) "myfile.txt" > STDOUT 

Note that it's also possible to install system commands of your own choosing. The method def_system_command will accomplish this. For example, here we define two methods ls and ll, which will list files in the current directory (short and long listings, respectively).


 # Method name is identical to command... # only one parameter necessary Shell.def_system_command "ls" # Two parameters needed here Shell.def_system_command "ll", "ls -l" sh = > STDOUT   # Short listing sh.ll > STDOUT   # Long listing 

You will notice that in many cases we explicitly send output to STDOUT. This is because output from a Shell command doesn't automatically go anywhere. It's simply associated with the Filter object until that object is connected to a file or an IO object.

Other Notes on shell.rb

The transact method will execute a block using the receiver for its context. Thus we can use this shorthand:


 sh = sh.transact do   echo("A line of data") > "somefile.txt"   cat("somefile.txt","otherfile.txt") > "thirdfile"   cat("thirdfile") | tee("file4") > STDOUT end 

There is an iterator foreach that will take either a file or a directory as a parameter. If it is a file, it will iterate over the lines of that file; if it is a directory, it will iterate over the filenames in that directory.


 sh = # List all lines in /tmp/foo sh.foreach("/tmp/foo") { |l| puts l } # List all files in /tmp sh.foreach("/tmp") { |f| puts f } 

There are pushdir and popdir methods that will save and restore the current directory, respectively. Aliases are pushd and popd. The method pwd will determine the current working directory; aliases are getwd, cwd, and dir.


 sh = "/home" puts sh.pwd      # /home sh.pushd "/tmp" puts sh.pwd      # /tmp sh.popd puts sh.pwd      # /home 

For convenience, numerous methods are imported into Shell from various sources, including the File class, the FileTest module, and the ftools.rb library. This saves the trouble of doing requires and includes, creating objects, qualifying method calls, and so on.


 sh = flag1 = sh.exist? "myfile"      # Test file existence sh.delete "somefile"            # Delete a file sh.move "/tmp/foo", "/tmp/bar"  # Move a file 

There are other features of the Shell library we don't cover here. See the associated documentation for more details.




The Ruby Way
The Ruby Way, Second Edition: Solutions and Techniques in Ruby Programming (2nd Edition)
ISBN: 0672328844
EAN: 2147483647
Year: 2000
Pages: 119
Authors: Hal Fulton

Similar book on Amazon © 2008-2017.
If you may any questions please contact us: