Posts Tagged: bash

Using dd in OS X

Doing device level copies with dd is a reasonably common Linux task, but not something OS X users typically do. However, if you find yourself needing to write an image file1 to a microSD card or some other media then here’s a simple guide to using it.

First, you’ll want to see the device labels.

diskutil list
/dev/disk0
   #:                       TYPE NAME                    SIZE       IDENTIFIER
   0:      GUID_partition_scheme                        *250.1 GB   disk0
   1:                        EFI                         209.7 MB   disk0s1
   2:                  Apple_HFS Macintosh HD            249.7 GB   disk0s2
/dev/disk2
   #:                       TYPE NAME                    SIZE       IDENTIFIER
   0:     FDisk_partition_scheme                        *2.0 GB     disk2
   1:                 DOS_FAT_32 THUMB_DRIVE             2.0 GB     disk2s1

The output from above shows that we have a mounted 2GB USB flash drive named “THUMB_DRIVE” that has been given the identifier /dev/disk2. To write to it we need to unmount it, but ejecting it in the normal Mac way won’t work here.

diskutil unmountDisk /dev/disk2

There we go! Now we just need to write our image file.

dd if=inputfile.img of=/dev/disk2

The shell will appear to hang, but you can check disk activity to see that it’s writing. Once the command returns you’re done!

  1. Frequently these guides will talk about using Win32DiskImager on Windows

pbpaste & pbcopy in Mac OS X (or: Terminal + Clipboard = Fun!)

The OS X shell is very powerful, but some wonderfully useful commands are almost entirely unknown to the community at large. Two of these forgotten commands are pbcopy and pbpaste. Let’s take a quick look at what they can do.

pbcopy

This command allows you to copy text from stdin into the clipboard1 buffer. Trivial example:

echo 'Hello World!' | pbcopy

“Hello World!” is now in your clipboard.

pbpaste

Pastes from your clipboard to stdout. Trivial example:

echo `pbpaste`

This will echo the contents of your clipboard. If you’re following along you’ll see “Hello World!”.

What Can I Do With These?

What can’t you do! Oh, you want examples? Well…

  • You could grab the output of a grep/awk/sed to paste into IM/IRC.
  • You could use a macro tool (like iKey, QS, et cetera) to create text modifying workflows that grab highlighted text, manipulate it, and replace it inline.
  • You could pull changelogs from svn into the clipboard when tagging for release so you could email them to coworkers.

Let me know what amazing things you come up with to enhance your own productivity!

  1. or pasteboard, hence the prefix “pb”

Fixing GrowlMail in 10.6.4 (Mail 4.3)

Update 2: Fix for 10.6.7 and Mail 4.5
Update: Fix for 10.6.5 and Mail 4.4

Another OS X release, another broken GrowlMail bundle. I did a post just like this for 10.6.2. Check it out if you want more background on why this occurs.

Easy Fix

Download a pre-patched GrowlMail.bundle and drop it in your ~/Library/Mail/Bundles/ directory1. If you want it available to multiple users on your system, use /Library/Mail/Bundles/.

Download patched bundle

If you use this method you’re all set; no need to use the command line solution below.

Add New UUIDs to SupportedPluginCompatibilityUUIDs

If you have already had your plugins disabled by opening Mail.app you’ll need to look in ~/Library/Mail (or /Library/Mail if you installed globally) and move the files back to the active bundles directory. They’ll typically be in Bundles (Disabled), so quit Mail, find them, and move them back into the proper directory.

If you have a local installation:

defaults write ~/Library/Mail/Bundles/GrowlMail.mailbundle/Contents/Info SupportedPluginCompatibilityUUIDs -array-add "E71BD599-351A-42C5-9B63-EA5C47F7CE8E"
defaults write ~/Library/Mail/Bundles/GrowlMail.mailbundle/Contents/Info SupportedPluginCompatibilityUUIDs -array-add "B842F7D0-4D81-4DDF-A672-129CA5B32D57"

Global installation:

defaults write /Library/Mail/Bundles/GrowlMail.mailbundle/Contents/Info SupportedPluginCompatibilityUUIDs -array-add "E71BD599-351A-42C5-9B63-EA5C47F7CE8E"
defaults write /Library/Mail/Bundles/GrowlMail.mailbundle/Contents/Info SupportedPluginCompatibilityUUIDs -array-add "B842F7D0-4D81-4DDF-A672-129CA5B32D57"
  1. ~ means your home directory if you’re unfamiliar with the syntax. You can click the home icon on your Finder sidebar if you’re still confused

Bash Productivity Enhancers

Bash is an extremely powerful shell, but its shortcuts are not readily apparent. Here are a few shortcuts and tips that I’ve noticed many (already proficient) bash users are not aware of. You can also check out Improved Bash History and More Useful Bash/Terminal Settings for more ideas for improving your bash productivity.

Bash Navigation Shortcuts

When editing a long command, there are quite a few navigation and editing shortcuts. By default bash typically operates in emacs mode.

  • Ctrl-A to go to the beginning of the line
  • Ctrl-E to go to the end of a line.
  • Ctrl-W will cut the current word (searching backward)
  • Ctrl-U will cut everything before the cursor
  • Ctrl-K cuts everything after the cursor
  • Ctrl-Y pastes the last text that was cut
  • Ctrl-T swaps the order of the last two characters entered1
  • Meta-B will move the cursor back one word
  • Meta-F will move the cursor forward one word

Meta keys are a bit tricky since they can differ based on your terminal application. On Windows/Linux it is typically Alt and on Mac OS X Terminal.app defaults to using Esc (but you can change it to option/alt in the preferences).

However, bash also has a vi/vim editing mode. To enable this type “set -o vi”. At this point all the typical vi shortcuts are available if you enter command mode (by hitting Esc). I don’t recommend using this unless you are very comfortable with vi already.

reverse-i-search

You can search through your history and rapidly find a command used previously with reverse-i-search. To invoke, press Ctrl-R and start typing. If you have multiple matches, hit Ctrl-R to cycle through them all. When coupled with an improved bash history this is an extraordinarily useful tool.

Controlling Tasks in Bash

Bash allows you to stop, background, and foreground tasks. To background a process before it starts simply add & to the end of your command.2

mycommand &
[1] 1922

If you have an already running task and you’d like to stop it press Ctrl-Z. This task will obtain a job number (the number in brackets).

[1]+  Stopped                 mycommand

You can then resume the task in the foreground with fg # or background it with bg #. To see a list of jobs that have been backgrounded or stopped type jobs.

Redirecting stderr/stdout in Bash

Bash has two main output buffers: stderr and stdout. Both of these, by default, output to your terminal window.

  • To redirect stdout to a file add > /path/to/output
  • To redirect stderr to a file add 2> /path/to/output
  • To redirect stderr into stdout add 2>&1
  1. This shortcut is available in both emacs and vi mode, but I’ve placed it here since it uses the Control key.
  2. Output from stdout and stderr will continue to appear in your terminal, so consider redirecting them if needed.

Fixing GrowlMail for Mail 4.2

Update 3: Fix for 10.6.7 and Mail 4.5
Update 2: Fix for 10.6.5 and Mail 4.4
Update: Fix for 10.6.4 and Mail 4.3

Lately Apple has been revving the version number (and plugin compatibility UUID) of Mail.app with every version of 10.6. This breaks bundles like GrowlMail even when they are still compatible. The easy fix (although not necessarily the best if it turns out an update is required!) is to run a few commands in Terminal to add the new UUIDs1 to the SupportedPluginCompatibilityUUID key in the Info.plist.2

If you have already had your plugins disabled by opening Mail.app you’ll need to look in ~/Library/Mail (or /Library/Mail if you installed globally) and move the files back to the active bundles directory. They’ll typically be in Bundles (Disabled), so quit Mail, find them, and move them back into the proper directory.

Once you’ve gotten the files moved into the proper location use either the local installation or global installation commands below (depending on where you found your bundles). To run them, simply copy/paste them into a Terminal window.3

For GrowlMail (assuming local installation)

defaults write ~/Library/Mail/Bundles/GrowlMail.mailbundle/Contents/Info SupportedPluginCompatibilityUUIDs -array-add "2F0CF6F9-35BA-4812-9CB2-155C0FDB9B0F"
defaults write ~/Library/Mail/Bundles/GrowlMail.mailbundle/Contents/Info SupportedPluginCompatibilityUUIDs -array-add "0CB5F2A0-A173-4809-86E3-9317261F1745"

For GrowlMail (global installation)

defaults write /Library/Mail/Bundles/GrowlMail.mailbundle/Contents/Info SupportedPluginCompatibilityUUIDs -array-add "2F0CF6F9-35BA-4812-9CB2-155C0FDB9B0F"
defaults write /Library/Mail/Bundles/GrowlMail.mailbundle/Contents/Info SupportedPluginCompatibilityUUIDs -array-add "0CB5F2A0-A173-4809-86E3-9317261F1745"

Update: Letterbox has been updated, but the above instructions can be adapted for any future OS update that breaks compatibility.

Update 2: You can download a pre-patched copy if you don’t want to follow the above instructions. Just unzip it and drop it in your bundles directory.

Update 3: GrowlMail 1.2.1 has been released, which fixes 10.6.2 compatibility. This issue will likely occur again with 10.6.3 though!

  1. 2F0CF6F9-35BA-4812-9CB2-155C0FDB9B0F for Mail.app v4.2 and 0CB5F2A0-A173-4809-86E3-9317261F1745 for the Message framework. These were released with OS X 10.6.2.
  2. These UUIDs can be found in /Applications/Mail.app/Contents/Info.plist and /System/Library/Frameworks/Message.framework/Resources/Info.plist for when they inevitably change again.
  3. Terminal is found in /Applications/Utilities if you’ve never used it before. You’ll see a prompt and you can paste the commands in and hit enter.

Find A Matching Certificate And Key Pair

If you have a list of keys and SSL certs and don’t know which cert belongs with which key, here’s a script for you. It’s not efficient (nested for loop!), but it gets the job done quickly.1

#!/bin/bash
for i in `ls *.key` 
do
key_mod=`openssl rsa -noout -in $i -modulus`
for j in `ls *.cer`
do
x509_mod=`openssl x509 -noout -in $j -modulus`
if [ "$x509_mod" == "$key_mod" ]; then
echo "$j matches $i"
fi 
done
done
  1. If bash allowed multidimensional or associative arrays this would be trivial to optimize.