I.2. Writing Scripts

Write a script to carry out each of the following tasks.

Easy

Home Directory Listing

Perform a recursive directory listing on the user's home directory and save the information to a file. Compress the file, have the script prompt the user to insert a floppy, then press ENTER. Finally, save the file to the floppy.

Converting for loops to while and until loops

Convert the for loops in Example 10-1 to while loops. Hint: store the data in an array and step through the array elements.

Having already done the "heavy lifting", now convert the loops in the example to until loops.

Changing the line spacing of a text file

Write a script that reads each line of a target file, then writes the line back to stdout, but with an extra blank line following. This has the effect of double-spacing the file.

Include all necessary code to check whether the script gets the necessary command line argument (a filename), and whether the specified file exists.

When the script runs correctly, modify it to triple-space the target file.

Finally, write a script to remove all blank lines from the target file, single-spacing it.

Backwards Listing

Write a script that echoes itself to stdout, but backwards.

Primes

Print (to stdout) all prime numbers between 60000 and 63000. The output should be nicely formatted in columns (hint: use printf).

Unique System ID

Generate a "unique" 6-digit hexadecimal identifier for your computer. Do not use the flawed hostid command. Hint: md5sum /etc/passwd, then select the first 6 digits of output.

Backup

Archive as a "tarball" (*.tar.gz file) all the files in your home directory tree (/home/your-name) that have been modified in the last 24 hours. Hint: use find.

Safe Delete

Write, as a script, a "safe" delete command, srm.sh. Filenames passed as command-line arguments to this script are not deleted, but instead gzipped and moved to a /home/username/trash directory. At invocation, the script checks the "trash" directory for files older than 48 hours and deletes them.

Medium

Managing Disk Space

List, one at a time, all files larger than 100K in the /home/username directory tree. Give the user the option to delete or compress the file, then proceed to show the next one. Write to a logfile the names of all deleted files and the deletion times.

Making Change

What is the most efficient way to make change for $1.68, using only coins in common circulations (up to 25c)? It's 6 quarters, 1 dime, a nickel, and three cents.

Given any arbitrary command line input in dollars and cents ($*.??), calculate the change, using the minimum number of coins. If your home country is not the United States, you may use your local currency units instead. The script will need to parse the command line input, then change it to multiples of the smallest monetary unit (cents or whatever). Hint: look at Example 23-4.

Quadratic Equations

Solve a "quadratic" equation of the form Ax^2 + Bx + C = 0. Have a script take as arguments the coefficients, A, B, and C, and return the solutions to four decimal places.

Hint: pipe the coefficients to bc, using the well-known formula, x = ( -B +/- sqrt( B^2 - 4AC ) ) / 2A.

Lucky Numbers

A "lucky number" is one whose individual digits add up to 7, in successive additions. For example, 62431 is a "lucky number" (6 + 2 + 4 + 3 + 1 = 16, 1 + 6 = 7). Find all the "lucky numbers" between 1000 and 10000.

Alphabetizing a String

Alphabetize (in ASCII order) an arbitrary string read from the command line.

Parsing

Parse /etc/passwd, and output its contents in nice, easy-to-read tabular form.

Pretty-Printing a Data File

Certain database and spreadsheet packages use save-files with comma-separated values (CSVs). Other applications often need to parse these files.

Given a data file with comma-separated fields, of the form:
Jones,Bill,235 S. Williams St.,Denver,CO,80221,(303) 244-7989
Smith,Tom,404 Polk Ave.,Los Angeles,CA,90003,(213) 879-5612
...
Reformat the data and print it out to stdout in labeled, evenly-spaced columns.

Difficult

Logging File Accesses

Log all accesses to the files in /etc during the course of a single day. This information should include the filename, user name, and access time. If any alterations to the files take place, that should be flagged. Write this data as neatly formatted records in a logfile.

Strip Comments

Strip all comments from a shell script whose name is specified on the command line. Note that the "#! line" must not be stripped out.

HTML Conversion

Convert a given text file to HTML. This non-interactive script automatically inserts all appropriate HTML tags into a file specified as an argument.

Strip HTML Tags

Strip all HTML tags from a specified HTML file, then reformat it into lines between 60 and 75 characters in length. Reset paragraph and block spacing, as appropriate, and convert HTML tables to their approximate text equivalent.

XML Conversion

Convert an XML file to both HTML and text form.

Morse Code

Convert a text file to Morse code. Each character of the text file will be represented as a corresponding Morse code group of dots and dashes (underscores), separated by whitespace from the next. For example, "script" ===> "... _._. ._. .. .__. _".

Hex Dump

Do a hex(adecimal) dump on a binary file specified as an argument. The output should be in neat tabular fields, with the first field showing the address, each of the next 8 fields a 4-byte hex number, and the final field the ASCII equivalent of the previous 8 fields.

Emulating a Shift Register

Using Example 26-6 as an inspiration, write a script that emulates a 64-bit shift register as an array. Implement functions to load the register, shift left, and shift right. Finally, write a function that interprets the register contents as eight 8-bit ASCII characters.

Determinant

Solve a 4 x 4 determinant.

Hidden Words

Write a "word-find" puzzle generator, a script that hides 10 input words in a 10 x 10 matrix of random letters. The words may be hidden across, down, or diagonally.

Anagramming

Anagram 4-letter input. For example, the anagrams of word are: do or rod row word. You may use /usr/share/dict/linux.words as the reference list.

Playfair Cipher

Implement the Playfair (Wheatstone) Cipher in a script.

The Playfair Cipher encrypts text by substitution of each 2-letter "digram" (grouping). Traditionally, one would use a 5 x 5 letter scrambled alphabet code key square for the encryption and decryption.

   C O D E S
   A B F G H
   I K L M N
   P Q R T U
   V W X Y Z

Each letter of the alphabet appears once, except "I" also represents
"J". The arbitrarily chosen key word, "CODES" comes first, then all the
rest of the alphabet, skipping letters already used.

To encrypt, separate the plaintext message into digrams (2-letter
groups). If a group has two identical letters, delete the second, and
form a new group. If there is a single letter left over at the end,
insert a "null" character, typically an "X".

THIS IS A TOP SECRET MESSAGE

TH IS IS AT OP SE CR ET ME SA GE

For each digram, there are three possibilities.
----------------------------------------------
1) Both letters will be on the same row of the key square
   For each letter, substitute the one immediately to the right, in that
   row. If necessary, wrap around left to the beginning of the row.

or

2) Both letters will be in the same column of the key square
   For each letter, substitute the one immediately below it, in that
   row. If necessary, wrap around to the top of the column.

or

3) Both letters will form the corners of a rectangle within the key
   square. For each letter, substitute the one on the other corner the
   rectangle which lies on the same row.


The "TH" digram falls under case #3.
G H
M N
T U           (Rectangle with "T" and "H" at corners)

T --> U
H --> G


The "SE" digram falls under case #1.
C O D E S     (Row containing "S" and "E")

S --> C  (wraps around left to beginning of row)
E --> S

=========================================================================

To decrypt encrypted text, reverse the above procedure under cases #1
and #2 (move in opposite direction for substitution). Under case #3,
just take the remaining two corners of the rectangle.


Helen Fouche Gaines' classic work, "Elementary Cryptoanalysis" (1939), gives a
fairly detailed rundown on the Playfair Cipher and its solution methods.

This script will have three main sections

  1. Generating the "key square", based on a user-input keyword.

  2. Encrypting a "plaintext" message.

  3. Decrypting encrypted text.

The script will make extensive use of arrays and functions.

--

Please do not send the author your solutions to these exercises. There are better ways to impress him with your cleverness, such as submitting bugfixes and suggestions for improving this book.