TweetFollow Us on Twitter

Back to bash Basics: Part 2 Time to Advance Ourselves

Volume Number: 21 (2005)
Issue Number: 11
Column Tag: Programming

Mac In The Shell

Back to bash Basics: Part 2 Time to Advance Ourselves

by Edward Marczak

With any exercise, you need to continually push yourself. Without that extra effort, what once was a challenge becomes easy, something to drift through. At the same time, you may be missing advanced techniques that make other areas easier or more efficient. Similarly, shell scripting can go many layers deep, and you can exercise your knowledge in many ways. Last month in, "Back to bash Basics Part 1," we focused on flow control. You may have noticed some of the things I didn't cover explicitly. There's always more to learn! Let's tie up those loose ends.

More Looping

Since we discussed looping constructs so much last month, that's where we'll pick up. In the select example, you'll see a break statement - that could use some explanation. break simply terminates the current loop. If it were removed from the select example, you would be asked repeatedly which file you want to inspect. Let's see what that would look like:

#!/bin/bash

select theItem; do
        if [ $theItem ]; then
                file $theItem
        fi
done

When this is run, the output looks like this:

Jack-Kerouak:~/bin marczak$ ./st.sh *
1) BidToJob.dmg 
2) bomcheck.sh
3) cl.txt
4) createdmg
5) diskrep.sh
6) exscript
#? 3
cl.txt: ASCII text
#? 4
createdmg: ASCII text
#? 5
diskrep.sh: Bourne-Again shell script text executable
#? ^C

Notice that this time, we need to press ctrl-c to stop the program. break applies to any loop:

#!/bin/bash
for i in $*;
        do
        if [ ! -O $i ]; then
                echo You do not own $i!  I am outta here!
                break
        fi
        echo $i is your file!
done

Running as me, I'm shown:

$ ./bt.sh *
BidToJob.dmg is your file!
bomcheck.sh is your file!
bt.sh is your file!
cl.txt is your file!
[...clipped for brevity]

Running in that same directory as root gives us:

# ./bt.sh *
You do not own BidToJob.dmg! I am outta here!

AOT (or, how the shell will separate files)

Have you ever crossed your AOT (Acronym Overload Threshold)? "There's a problem with the RIP!" Raster Image Processor, or Routing Information Protocol? While there's only so many TLAs (Three Letter Acronyms) that you can deal with, I need you add one more: IFS (no, not Iterative Fractal Systems!). The shell uses the Internal Field Separator to determine how to break apart tokens, and how to separate incoming parameters. By default, IFS is equal to space, tab and newline.

When we discussed the for loop last month, several things were quickly touched upon that can be expanded. In addition to the $@ variable, which expands to individual double-quoted strings, there is the $* variable, which is a single string containing each positional parameter. How do you know where each parameter breaks? $* separates each parameter by using the first character of your IFS variable. We'll get back to how this can be very useful.

Also, last month showed an example that looked something like this:

FILES=`ls *.sh`

for i in $FILES
do
        ...
done

This example 'just works' because ls *.sh will separate its output with linefeeds. Hey, that's one of the characters in IFS by default! What good fortune! This same example will fall apart if you reassign the IFS variable prior to the loop:

IFS="-"
FILES=`ls *.sh`
for i in $FILES; do
...
done

$i will still hold $FILES, but it won't be tokenized - not the way you'd expect (the line feeds will still be in there, but $i won't break on them).

So, then, why would we ever touch IFS? Well, what if you wanted to search through something that is not broken up by a space, newline or tab? Like $PATH, for instance:

#!/bin/bash

IFS=:

for theDir in $PATH
do
        theLatest=`ls -lotr $theDir | tail -1`
        echo Newest file in $theDir:
        echo $theLatest
        echo
done

This simply goes through our $PATH and tells us the newest file in each directory. Could be useful.

Oh, and another thing

Like Apple, shell scripting always seems to have "one more thing." For this month, this thing comes in the form of being able to effectively handle parameters. Time to introduce shift and getopts.

When writing a script, parameters can be accessed a few ways. If you always rely on direct access ($1, $2...etc), you run into some limits. One way to simply loop through all parameters is to use shift. shift makes $1 = $2, $2 = $3...etc. You lose the first value that was assigned to $1. To look for a few specific parameters, you can loop through the values:

#!/bin/bash

while [ `echo $1 | grep "-"` ]; do
        case $1 in
                -a ) echo "You supplied the -a flag";;
                -b ) echo "You supplied the -b flag";;
                -c ) echo "You supplied the -c flag";;
                * ) echo "Usage: $0 -a -b -c";
                exit 1;;
        esac    
        shift
done

Run this code and you'll see:

$ ./shifttest.sh -b -a
You supplied the -b flag
You supplied the -a flag

Now, shift is cool, and still comes in handy, but to truly handle command-line options smoothly, we have to employ getopts. Sure, you can roll your own each time, however, people have come to expect their options to behave in certain ways. One should be able to combine options, as with tar, for example: tar -xzvf blah.tar.gz. Basically, you don't need to roll your own because getopts exists.

getopts allows you to handle options in a standard way. Seeing it in action is the quickest way to get up to speed:

#!/bin/bash

while getopts ":xyz:t" theOption; do
        case $theOption in
                x ) echo "Option x chosen";;
                y ) echo "Option $theOption chosen";;
                z ) echo "Option z chosen with argument: $OPTARG";;
                t ) echo "Option t chosen";;
                \? ) echo "Unknown option chosen"
                        exit 1;;
                * ) echo "You need to supply an option!"
                        exit 2;;
        esac
done

getopts is designed to be dumped in a loop that will feed it arguments passed into the script. It accepts a string that defines the allowed options, followed by a variable that will hold the current option, sans the "-" or "+" (nicely, either are allowed). Using getopts will define two variables: $OPTIND, the current index and $OPTARG, the current argument passed with an option. Running this produces this output:

$ ./gotest.sh -yxz test
Option y chosen
Option x chosen
Option z chosen with argument: test

The string that getopts accepts can only contain letters and the colon character. Each letter is an option you wish to support. If a letter is followed by a colon, that tells getopts that an argument is required. By having a lead colon character in the parameter list string, you suppress the error message that getopts will print if an option is not recognized. In either case, an unrecognized option will set the variable to "?", so you can deal with it.

Put it all Together

I've gotten a request or two asking how to deal with math in the shell. While there are specialized CLI apps that will deal with arithmetic, the shell can do some basic functions, and sometimes, that's all you need. The trick is the underused declare statement. declare tells the shell how you want to treat variables, which are strings by default. So, this doesn't do what one would expect:

$ number1=7
$ number2=8
$ total=number1*number2

When you echo $total, you get "number1*number2": strings. We need to tell the shell that $total should be treated as an integer:

$ declare -i total
$ total=number1*number2
$ echo $total
56

Much better! declare can define several different types of variables:

-a   variable is an array
-i   treat as integer
-r   makes variable read-only
-x   automatic export (like the 'export' built-in)

There are some others, but this is all we need concentrate on for now. All of the usual suspects are available as mathematic operators:

+   Addition
-   Subtraction
*   Multiply
/   Divide
%   Remainder
<<  Bit-shift left
>>  Bit-shift right
&   Bitwise and
|   Bitwise or
~   Bitwise not
!   Bitwise not
^   Xor

In addition to declare-ing a variable to be an integer, you can use let to make the assignment:

let theTotal='5 * 7'

Ah, let....brings me back to my C64 BASIC days...

Now, you should be able to write fairly sophisticated shell script that includes slick input processing, good error handling and even some basic computations!

Make Yourself Useful...

...to everyone. Just remember that bash scripting will help you not only with OS X, but with Linux, IRIX, FreeBSD, and even Windows - if you install a Unix shell there (which can be had for free from Cygwin or Microsoft).

This month highlights the fact that shell scripting is relatively easy, can be fun and powerful. Even better, you'll find bash built-in to every OS X machine you touch! Let this all sink in: while I'll get back to bash scripting in future columns, more Unix detours next month!


Ed Marczak keeps it simple. Tech simplicity at http://www.radiotope.com

 
AAPL
$98.15
Apple Inc.
-0.23
MSFT
$43.58
Microsoft Corpora
-0.31
GOOG
$587.42
Google Inc.
+1.81

MacTech Search:
Community Search:

Software Updates via MacUpdate

Knock 1.1.7 - Unlock your Mac by knockin...
Knock is a faster, safer way to sign in. You keep your iPhone with you all the time. Now you can use it as a password. You never have to open the app -- just knock on your phone twice, even when it's... Read more
Mellel 3.3.6 - Powerful word processor w...
Mellel is the leading word processor for OS X and has been widely considered the industry standard since its inception. Mellel focuses on writers and scholars for technical writing and multilingual... Read more
LibreOffice 4.3.0.4 - Free Open Source o...
LibreOffice is an office suite (word processor, spreadsheet, presentations, drawing tool) compatible with other major office suites. The Document Foundation is coordinating development and... Read more
Freeway Pro 7.0 - Drag-and-drop Web desi...
Freeway Pro lets you build websites with speed and precision... without writing a line of code! With it's user-oriented drag-and-drop interface, Freeway Pro helps you piece together the website of... Read more
Drive Genius 3.2.4 - Powerful system uti...
Drive Genius is an OS X utility designed to provide unsurpassed storage management. Featuring an easy-to-use interface, Drive Genius is packed with powerful tools such as a drive optimizer, a... Read more
Vitamin-R 2.15 - Personal productivity t...
Vitamin-R creates the optimal conditions for your brain to work at its best by structuring your work into short bursts of distraction-free, highly focused activity alternating with opportunities for... Read more
Toast Titanium 12.0 - The ultimate media...
Toast Titanium goes way beyond the very basic burning in the Mac OS and iLife software, and sets the standard for burning CDs, DVDs, and now Blu-ray discs on the Mac. Create superior sounding audio... Read more
OS X Yosemite Wallpaper 1.0 - Desktop im...
OS X Yosemite Wallpaper is the gorgeous new background image for Apple's upcoming OS X 10.10 Yosemite. This wallpaper is available for all screen resolutions with a source file that measures 5,418... Read more
Acorn 4.4 - Bitmap image editor. (Demo)
Acorn is a new image editor built with one goal in mind - simplicity. Fast, easy, and fluid, Acorn provides the options you'll need without any overhead. Acorn feels right, and won't drain your bank... Read more
Bartender 1.2.20 - Organize your menu ba...
Bartender lets you organize your menu bar apps. Features: Lets you tidy your menu bar apps how you want. See your menu bar apps when you want. Hide the apps you need to run, but do not need to... Read more

Latest Forum Discussions

See All

Murl the Squirrel (Games)
Murl the Squirrel 1.0 Device: iOS Universal Category: Games Price: $.99, Version: 1.0 (iTunes) Description: Meet Murl. He is teased by a group of flying squirrels because he can't fly. Determined to show them he's can fly, he meets... | Read more »
Celleste (Games)
Celleste 0.1 Device: iOS Universal Category: Games Price: $2.99, Version: 0.1 (iTunes) Description: Lots of cute action with amazing 3D graphics and a new type of gameplay! Take control over the forces of the universe to help a group... | Read more »
Super Heavy Sword (Games)
Super Heavy Sword 0.0.1 Device: iOS Universal Category: Games Price: $.99, Version: 0.0.1 (iTunes) Description: Get Ready to Get HEAVY! Monster Robot Studios presents SUPER Heavy Sword! The sequel to the smash hit HEAVY sword which... | Read more »
Angels In The Sky (Games)
Angels In The Sky 1.00 Device: iOS Universal Category: Games Price: $6.99, Version: 1.00 (iTunes) Description: - This game is only for the iPhone 5s. please do not use the iPad, iPhone 5 or earlier devices.- Just touch or holding... | Read more »
80 Days (Games)
80 Days 1.0.2 Device: iOS Universal Category: Games Price: $4.99, Version: 1.0.2 (iTunes) Description: 1872, with a steampunk twist. Phileas Fogg has wagered he can circumnavigate the world in just eighty days. Choose your own route... | Read more »
Micromon (Games)
Micromon 1.0 Device: iOS Universal Category: Games Price: $.99, Version: 1.0 (iTunes) Description: 130+ Animated Monsters to Catch & Battle! No waiting, play at your own pace! Embark on an epic monster capture RPG like none... | Read more »
Empire Manager (Games)
Empire Manager 1.0 Device: iOS iPhone Category: Games Price: $3.99, Version: 1.0 (iTunes) Description: Become ruler of an empire. Manage your economy, develop technology, hire an army and conquer the world in this addictive turn-... | Read more »
Empire Manager HD (Games)
Empire Manager HD 1.0 Device: iOS Universal Category: Games Price: $7.99, Version: 1.0 (iTunes) Description: Become ruler of an empire. Manage your economy, develop technology, hire an army and conquer the world in this addictive... | Read more »
Star Admiral Review
Star Admiral Review By Rob Thomas on July 30th, 2014 Our Rating: :: ADMIRABLE ADMIRALSUniversal App - Designed for iPhone and iPad While this new digital CCG may feel a bit familiar, Star Admiral offers a sci-fi twist and galaxy’s... | Read more »
Zap! Pow! Become a Badass Wizard in Phan...
Zap! Pow! | Read more »

Price Scanner via MacPrices.net

iPad Cannibalization Threat “Overblown”
Seeking Alpha’s Kevin Greenhalgh observes that while many commentators think Apple’s forthcoming 5.5-inch panel iPhone 6 will cannibalize iPad sales, in his estimation, these concerns are being... Read more
Primate Labs Releases July 2014 MacBook Pro P...
Primate Labs’ John Poole has posted Geekbench 3 results for most of the new MacBook Pro models that Apple released on Tuesday. Poole observes that overall performance improvements for the new MacBook... Read more
Apple Re-Releases Bugfixed MacBook Air EFI Fi...
Apple has posted a bugfixed version EFI Firmware Update 2.9 a for MacBook Air (Mid 2011) models. The update addresses an issue where systems may take longer to wake from sleep than expected, and... Read more
Save $50 on the 2.5GHz Mac mini, plus free sh...
B&H Photo has the 2.5GHz Mac mini on sale for $549.99 including free shipping. That’s $50 off MSRP, and B&H will also include a free copy of Parallels Desktop software. NY sales tax only. Read more
Save up to $140 on an iPad Air with Apple ref...
Apple is offering Certified Refurbished iPad Airs for up to $140 off MSRP. Apple’s one-year warranty is included with each model, and shipping is free. Stock tends to come and go with some of these... Read more
$250 price drop on leftover 15-inch Retina Ma...
B&H Photo has dropped prices on 2013 15″ Retina MacBook Pros by $250 off original MSRP. Shipping is free, and B&H charges NY sales tax only: - 15″ 2.3GHz Retina MacBook Pro: $2249, $250 off... Read more
More iPad Upgrade Musings – The ‘Book Mystiqu...
Much discussed recently, what with Apple reporting iPad sales shrinkage over two consecutive quarters, is that it had apparently been widely assumed that tablet users would follow a two-year hardware... Read more
13-inch 2.5GHz MacBook Pro on sale for $999,...
Best Buy has the 13″ 2.5GHz MacBook Pro available for $999.99 on their online store. Choose free shipping or free instant local store pickup (if available). Their price is $100 off MSRP. Price is... Read more
Save up to $300 on an iMac with Apple refurbi...
The Apple Store has Apple Certified Refurbished iMacs available for up to $300 off the cost of new models. Apple’s one-year warranty is standard, and shipping is free. These are the best prices on... Read more
WaterField Unveils 15″ Outback Solo & 13″...
Hard on the heels of Apple’s refreshed MacBook Pro Retina laptops announcement, WaterField Designs has unveiled a 15-inch version of the waxed-canvas and leather Outback Solo and a 13-inch version of... Read more

Jobs Board

Sr. Product Leader, *Apple* Store Apps - Ap...
**Job Summary** Imagine what you could do here. At Apple , great ideas have a way of becoming great products, services, and customer experiences very quickly. Bring Read more
Sr Software Lead Engineer, *Apple* Online S...
Sr Software Lead Engineer, Apple Online Store Publishing Systems Keywords: Company: Apple Job Code: E3PCAK8MgYYkw Location (City or ZIP): Santa Clara Status: Full Read more
Sr Software Lead Engineer, *Apple* Online S...
Sr Software Lead Engineer, Apple Online Store Publishing Systems Keywords: Company: Apple Job Code: E3PCAK8MgYYkw Location (City or ZIP): Santa Clara Status: Full Read more
*Apple* Solutions Consultant (ASC) - Apple (...
**Job Summary** The ASC is an Apple employee who serves as an Apple brand ambassador and influencer in a Reseller's store. The ASC's role is to grow Apple Read more
Sr. Product Leader, *Apple* Store Apps - Ap...
**Job Summary** Imagine what you could do here. At Apple , great ideas have a way of becoming great products, services, and customer experiences very quickly. Bring Read more
All contents are Copyright 1984-2011 by Xplain Corporation. All rights reserved. Theme designed by Icreon.