MacOS X offers a brilliant example of integration between a state-of-the-art windowing GUI and a traditional command line interface and you can choose the kind of interface that most suits your current needs or that makes easier the task you are at. One task that is very easily done via the Aqua user interface is printing a bunch of documents on a given printer. All that you need for that is a Desktop Printer that you can drag your documents to. (Desktop printers can be created via the Printers menu in the Printer Setup Utility).

This is perfectly fine, where it not for the fact that I don’t like icons I use sporadically cluttering my desktop. Furthermore, when I need to print a group of documents, I am usually working from the command line — e.g., I want to print all jpeg pictures in a folder or print some html files to PDF. So the way I usually do this is thru the magic of the open command. Indeed, when you execute:

open -a "Printer Setup Utility"

this will print all listed files on the default printer. Of course, if you want to print to a different printer from your default one, this will not do. Fortunately, you can also set your default printer via the command line, by using the command:

lpoptions -d .

All in all, say that you have a PDF printer driver (i.e., a program that acts like a printer driver but will “print” to a PDF file) installed with the name “PDF_Printer”. You can send documents to it to be printed by executing:


$ lpoptions -d PDF_Printer
$ open -a "Printer Setup Utility" */*.jpg
$ lpoptions -d Color_Printer

If you have several printers and you don’t know which one was your default printer before switching to PDF_Printer, you can execute:

lpoptions -d

to read the current default printer before switching it. With all this bits, creating a shell script automating your specific workflow is a matter of minutes.

I find myself quite often needing executing a shell command when I am working in the Finder, say, for example, to “touch” a file in a certain folder on screen. What one needs to do in such cases is opening a Terminal window, drag and drop the folder icon on to it, preprend a “cd” to the folder path, and finally type the desired command.

All of this is readily accomplished in a very elegant way by means of the simple Automator workflow that’s described by the following snapshot (click to see it larger).

If you create the Automator workflow depicted above, and save it as a Finder workflow (see picture below),

you will be then able to right-click on any folder, or on the Desktop, and then choose ExecuteShellCommand from the Automator menu that will be displayed.

Thereafter, you will be asked for the command to execute. If you ran the workflow on a folder, then the command will be executes inside that folder. If you ran it on a file, then the command you specified will be passed the file as the last argument.

As said, this is useful when you want to carry out a one-shot operation, like touching a file (if it does not exist, you will need to run the workflow on the folder that’s going to contain it and specify the file name; if the file exists, you only need to run the workflow on that file and specify “touch” as a command to execute), opening a file with a given application (“open -a “), and so on…

If anyone finds interesting uses for this workflow, please let me know. Also welcome, since I am not really good at Automator :-) , are any suggestions as to better ways to implement it.

A few months ago, a friend of mine had her Firefox bookmark file deleted by way of a stupid bug. We tried everything we could to undelete the file by using several commercial tools we had available, but without any success.

After spending a few hours in complete frustration, I began missing the simplicity, and power, of dd. Some time earlier I had been able to recover a file that I had just rm-ed thanks to dd, so I was quite confident in it… but the hard drive was on a Windows machine… and, you know, when you got used to tools like dd, find, grep, sed, and alikes, then it’s too late for you to even remotely think of Windows as a “usable” OS — this, at least, my feeling. Hence, the frustration: I knew I could try to do something about it, but I saw myself with my hands tied in a totally unfriendly (to me, at least) environment. (Ok, I know, you can have cygwin on Win32, but aside from it not being quite “the same”, in my case it was out of question installing a few hundreds MB of SW on my friend’s machine, too risky…)

Then, inspired by the wonderful “target mode” of Powerbooks and iBooks, I tried to look for some way to remotely access the other machine’s hard drive and started digging the web… It was there that I read about the possibility to run a tiny nbd (Network Block Device) server on Windows that would allow my linux machine to access the Windows machine’s hard drive as if it were a local block device, and let me play on it with my favorite GNU tools. It looked promising, so I decided to give it a try…

It was not that easy. As it turned out, my linux kernel had no support for network block devices, so I had to look for the “Network block device support” under “Block Devices” in section “Device Drivers”. Then compile it in as a module (but I am not really sure that adding any module is always possible without recompiling the kernel), load it with modprobe nbd. This module allows linux to act as client to an nbd server… client? and where was the client, then?

I somehow found out about the linux network block device client and obviously my Debian distribution had it available, so installing and configuring it was a snap. By the way, don’t forget to choose the “raw” mode (as opposed to “filesystem” and “swap”)…

Then it was time to launch the nbd server on the Windows machine, what I did by executing the command:

nbdsrvr \\.\PHYSICALDRIVE0 9000 9

and then launched the client on my linux machine with the command:

nbd-client 192.168.1.4 9000 /dev/nbd0

Finally, my /dev/nbd0 block device was there waiting for dd to scan it… :-) To make things easier, and more manageable, I wrote a small Perl script accepting two parameters that would dump chunks of blocks in a sequence of files. The code follows…


#!/usr/bin/perl -w

#-- chunk size in blocks
$blocks = 100000;

#-- first chunk of blocks to dump in a file
$from = shift;
#-- last chunk of blocks to dump
$upto = shift;

#-- number of blocks to skip at the beginning of the device
#-- to skip OS files, assuming you are not trying to recover one.
$offset = 10000000;

for ($i = $from; $i <= $upto; $i++) {
  $skip = $offset + $i * $blocks;
  system("dd if=/dev/nbd0 of=./recv-$i count=$blocks skip=$skip");
}

That allowed me to dump the first, say, 50 chunks of 100000 blocks (around 50MB of data), in a series of files that I could grep in search for some string helpful to identify the Firefox bookmarks.html file. Then, I dumped another 50 and so on, until I had found what I was looking for… Not exactly an automated undelete, but very very powerful…

Know your tools…

29 October 2006

An interesting post from a good friend of mine about the importance of using extensible tools — he is a big emacs fan, so you better be prepared to what you can expect there… :-)

Just a quick note: one of Jao’s philosophical takes on emacs is that emacs is a full operating environment, you know, the thing you put on top of a running kernel… he is fully right at that, since you can do almost everything without leaving emacs (emailing, web browsing, programming, etc.) and everything is “nicely” (well, it depends, actually there’s much debate as to how nice emacs is… :-) ) integrated by means of the powerful elisp glue…

But there’s another side of the philosophy-coin: possibly emacs evolved as it is in order to fullfil a traditional gap of all UNIX-based OSes, which is the almost absolute lack of integration between different applications (in turn due to the lack of sufficiently high-level means of IPC). Thus, emacs first built an integration/extensibility layer at its core, then grew upon it in a way such that it has come to be what we all know.

But then, the most interesting question I can ask is: would emacs be the same, had you got that kind of (cross-application) integration/extensibility at the OS level? Or, from a different point of view: what if the “glueing-layer” that emacs offers were included in the OS itself? And then: is there such an OS somewhere around?

I use to work in a mixed OS environment, where Windows, MacOS, and linux machines coexist. And I am happy about the fact that I can use MacOS X as my main operating systems in a Windows-based network (you know, Exchange server for mail, Microsoft Office for everything, Windows shares everywhere…)… this would be, of course, utterly impossible if there were no Microsoft Office suite for MacOS X, but still it is a times a bit distressing…

For example, I often find myself emailing paths to files or folders hosted in some Windows shares to Windows users (as I said before, everyone uses Windows :-( ) that expect to receive an ugly path like

\\servername\sharename\rel_path

or they will complain… well, at first I used to copy the path from my xterm session (I live with many xterm sessions hanging around that I use as a sort of control center), then change all slashes to backslashes, then prefix the resulting string by the \\servername… clumsy and error prone, at best…

So, I thought of developing a simple Automator action that can generate the full pathname to a file accessible from my Mac (i.e., one that you can display in a Finder window), in one of three formats: native MacOS, UNIX/POSIX, and Windows format… so, thanks to an Automator workflow, I can simply right-click on a file and choose “Copy Path” to have what I need in my clipboard, ready to be pasted in a mail, word doc or whatever… Hnady for Terminal as well…

Here you can see a picture of a simple Automator Workflow using Copy Path:

Automator-CopyPath-Example

Looking for a place where to make it available here in WordPress (you can only upload images and text documents)… for the time being, send me a line, and I will mail you an image file.