pkg


There’s no sense naming files in the manifest file that people can’t access from the git checkout. In a complicated project there may be (intentionally) untracked files and perhaps multiple manifest files. There are many ways to check the manifest, but one way is to ask ‘git status’.

while read f; do
  [ -f $f ] \
  && git status --porcelain -uall $f \
  || echo "## $f"
done <MANIFEST

Non-existent files will be preceded by ‘##’ and non-tracked files will be preceded by ‘??’.

Advertisements

I wanted my default diff options in bazaar to be for side-by-side comparisons. This worked by editting my $HOME/.bazaar/bazaar.conf.

[ALIASES]
diff=diff --diff-options "--width=200 --side-by-side"

You’re tailing a file in the usual way

tail -n 80 -f log/production.log

but the writing process (or maybe logrotated) swaps it for a new file. Now your tail is left looking at the old version, which is stale. You could ctrl+c and restart the tail but that is tedious. The answer is to specify you want tail to follow the name of the file rather than the file descriptor. Now when a new file is swapped-in as a replacement, tail continues the way you always wanted.

tail -n 80 --follow=name log/production.log

Frequently I want to copy files or directories from within one tree and inject them into another tree. In such cases I want to preserve timestamps, ownerships, and permissions, including those of all parent directories on its path, and I don’t want unspecified children of directories nor siblings of files. Let’s look at doing that with the various common tools available: tar, rsync, cp, install, cpio, afio.

We’ll have a list of paths in /tmp/paths and the objective is to copy them from /tmp/source to /tmp/target. Most of these methods face the issue that they create ancestor directories fresh rather than copy them. The solution is to ensure /tmp/paths contains every directory in every path, always listing parents before children. For example, if aa/bb/cc/d.txt is a path, then aa, aa/bb, aa/bb/cc are also paths and are included in the file in that same order.

tar

tar -C /tmp/source -cf - --files-from /tmp/paths --no-recursion \
| \
tar -C /tmp/target -xf - --same-owner --atime-preserve --same-permissions

(If your tar doesn’t have a -C option, you can use the classic workaround as follows.)

(cd /tmp/source && tar -cf - --files-from /tmp/paths --no-recursion) \
| \
(cd /tmp/target && tar tar -xf - --same-owner --atime-preserve --same-permissions)

rsync

rsync -lptgod --files-from=/tmp/paths /tmp/source /tmp/target

This does exactly what we want, but the nice people designing the interface provide an even easier to remember set of options which is equivalent.

rsync -a --no-r --files-from=/tmp/paths /tmp/source /tmp/target

One big advantage of rsync is that you don’t need to include the prefix paths (ancestor dirs) in the paths file. Less prep and an easy-to-remember invocation. Thank you rsync.

cp

while read path; do
  echo /tmp/source/$path
done </tmp/paths \
| \
xargs cp -pd --parents -t /tmp/target

While an interesting invocation of cp it doesn’t meet the requirements; it copies everything to /tmp/target/tmp/source instead. In fact I failed to find a successful invocation of cp, even putting it in a loop (and so losing efficiency), because it declines to copy a directory by itself.

Others

install is very similar to cp, but even less useful for this task (because it doesn’t preserve ownership). cpio has a terrible manpage and afio seems to have fallen out of favour (superseded by cpio). (To be fair, there’s no point them competing with tar and rsync in this market.)

See also: Using rsync to copy just a directory

Recently I’ve found myself editing in excess of twenty source files concurrently; time to use a vim session so that I don’t need to specify the list of files again each time I start editing. Basic usage is simple.
vim firstfile then :e secondfile, etc. At any time after they’re all open, do :mksession! which will create a Session.vim file in your initial location. When you want to open up those same files again, use vim -S and you’re there. One great advantage of this is that :b8 for example, will always take you to the same file, even if you close and re-open that file — vim knows that you appreciate consistency and does its best to help.

However, there is one small mystery. Say you originally opened up a, b, c and then did :ls. You would see that a was buffer 1 and c was buffer 3. But when you re-open your session, you find that a is buffer 2 and c is buffer 4 — why no buffer 1? The answer is that vim kept buffer 1 for your headline file, but you specified none. I still find this a bit weird, but the working invocation is vim a -S. Now it has opened a as buffer 1 and all other files mentioned in Session.vim as the remaining buffers, so it looks again as it did originally.

Note that Session.vim contains a cd command (which you can edit of course) so you could keep several session files in your base location, relying on the individual session file to set you up in the appropriate destination. For example, have core.vim and plugins.vim in your home directory. Then let vim -S core.vim take you to the base directory for editing those files.

Note also that a huge degree of behaviour is configurable via the sessionoptions setting.

I love my kindle (3) — it has brought me back to reading fiction, reading more non-fiction than ever, being more productive in my work-related reading, and just appreciating quality texts. But to my surprise, I love its non-reading features almost as much. The ‘experimental’ browser is handy if you’re selective about which web pages you bookmark, and the couple of games might be handy while nervously passing time in a waiting room. Yesterday my daughter didn’t want to travel home in the car — offered her some music courtesy of the kindle and soon she was falling asleep to Rod Stewart. Best of all, when it’s asleep itself, it is my digital picture frame, showing some of my favourite family pictures without using any of its amazing battery life.

Here I’ll jot down my steps for quickly achieving top quality images tuned for the kindle while minimising strain on CPU and diskspace. (These notes are for B&W 6-inch (600 x 800) kindle screens, not DX nor Fire.)

First create a brand new folder to work in and put in it brand new copies of your favourite pictures. (In picassa the easiest way is to browse for a picture you like, then locate it on disk (<Ctrl>+<Rtn>) then copy & paste to your new folder.) For me that means high resolution colour images from my camera, which happen to be jpg. In picassa, define a ‘Custom format’ of 600 x 800 called “Kindle”. Point picassa at your new folder and carry out the following for each picture.

  1. View and Edit (shortcut = <Rtn>)
  2. Basic Fixes > Crop
  3. Select Kindle, drag the rectangle around to suit
    • Quickest is to choose one of the proposed crops, possible using ‘rotate’, then resize/move to suit
    • Keep your produced images either all portrait or all landscape
  4. Effects > B&W
  5. Effects > Glow
    • This is for cute pics of my daughter; might not be appropriate for your selection
  6. Basic Fixes > Auto Contrast
  7. Save

Your picture is now in the right ratio with pretty decent cropping and contrast, but it’s a fair bit bigger than it needs to be. If you don’t care about diskspace or how quickly pictures are rendered then you can skip the next section.

Now we open up gimp and optimise the file format.

  1. File > Open
  2. Image > Mode > Grayscale
  3. Image > Scale Image
  4. Set resolution to 166
  5. Un-chain Width & Height so they can have unlinked values
  6. Set them to be 600 and 800
  7. You probably want ‘Cubic’ interpolation
  8. File > Save As
  9. Change suffix to “png”
  10. Untick everything except ‘Save resolution’

Your picture is now in a smaller (png) file. (Might be worth comparing your ‘before’ and ‘after’ sizes, but with my pictures they became much smaller — less than 250 kB.)

If your kindle doesn’t have a ‘pictures’ folder, create one at its root and then create a subfolder for your pictures (eg /kindle/too_cute). Put your .png pictures into the sub-folder, go to ‘Home’ in the kindle, refresh via <Alt>+<z>, then you should be able to open the folder of pictures in the same way you would access a book.

To have these pictures be your new screensaver images, you need to follow the steps at Kindle Screensaver Hack, putting your pictures in the /linkss/screensavers folder.

There are a couple of improvements that could be made to this recipe. It’s ok for twenty pictures, but if you were doing two hundred, you would want to use gimp’s scripting approach. The generated picture files have meta-data relating to the edits, but I’d much rather copy the meta-data (eg creation date) from the original files. One day I’ll write a perl script to copy selected meta-data from each jpg to the corresponding png.

There are many situations in which you would like something to run each time you save a file (or a process modifies a file). Since linux kernel 2.6 this has been possible via the inotify mechanism. All you need is a client package for whichever language (bash, perl, ruby, python, …) you want to use.
For perl we have liblinux-inotify2-perl and for bash we have inotify-tools which I’ll illustrate here.

In this example, each time one of the specified files is saved (in vim), the script of unit tests will be invoked. This particular line uses the fact that vim implements a ‘save’ by way of ‘move, move, delete’, so we detect the first ‘move’…

tests=test/cari_plugin_defaults.pl
sources="lib/Cari/Plugin/Defaults.pm lib/Cari/Plugin/Stash.pm"
while inotifywait -qqe MOVE_SELF $tests $sources; do ./$tests; done

This is useful in lots of examples where you want to quickly see the results of editing source file(s), for example editing LaTeX files.

(Update: My latest vim issues ‘MODIFY’ instead of ‘MOVE_SELF’, so you’ll want to test yourself using inotifywait filename.)

Next Page »