Section 14.4. Accessing Environment Variables


14.3. The Shell Library

Ruby isn't necessarily convenient to use as a scripting language in every situation. For example, a bash 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. (It doesn't always work well on Windows.)

14.3.1. Using Shell for I/O Redirection

The Shell class has two methodsnew and cdfor 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 = Shell.new             # Work in the current directory sh2 = Shell.cd("/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 = Shell.new # Print the motd file to stdout sh.cat("/etc/motd") > STDOUT # Print it again (sh.cat < "/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 (sh.cat "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... sh.cat("myfile.txt") > STDOUT # ...and this also. (sh.cat "myfile.txt") > STDOUT # TypeError! (a precedence problem) sh.cat "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 methodsls and llwhich 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 = Shell.new sh.ls > 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.

14.3.2. 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 = Shell.new sh.transact do   echo("A line of data") > "somefile.txt"   cat("somefile.txt","otherfile.txt") > "thirdfile"   cat("thirdfile") | tee("file4") > STDOUT end


The iterator foreach 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 = Shell.new # List all lines in /tmp/foo sh.foreach("/tmp/foo") {|l| puts l } # List all files in /tmp sh.foreach("/tmp") {|f| puts f }


The pushdir and popdir methods 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 = Shell.cd "/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, includes, creating objects, qualifying method calls, and so on.

sh = Shell.new 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 that we don't cover here. See the associated documentation for more details.




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

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net