Skip to navigation

Installing Digikam with fewer dependencies in Xubuntu/ Ubuntu Intrepid

February 5th, 2009

If you do

sudo aptitude install digikam

on Intrepid, you will see that aptitude would install loads of KDE packages (Dolphin and Konqueror, yikes). Apparently, this is because aptitude now by default also installs recommended packages as “dependencies”. To avoid this, use the -R flag to aptitude (see also man aptitude):

sudo aptitude install -R digikam

If you prefer Synaptic for the GUI, there is a global option there under Preferences, in the General tab.

Addendum

One issue is that you will not be able to use the Flickr upload plugin without Konqueror, as this version of Digikam uses Konqueror to authenticate you on Flickr. A workaround is to get the lateste KDE4 version of Digikam, which you can do by adding the following four repositories to /etc/apt/sources.list:

deb http://ppa.launchpad.net/digikam-experimental/ppa/ubuntu intrepid main
deb-src http://ppa.launchpad.net/digikam-experimental/ppa/ubuntu intrepid main
deb http://ppa.launchpad.net/kubuntu-experimental/ppa/ubuntu intrepid main
deb-src http://ppa.launchpad.net/kubuntu-experimental/ppa/ubuntu intrepid main

You’ll also have to add the key for each repository using (substitute key number for “9999”):

gpg --keyserver subkeys.pgp.net --recv-key 9999
gpg -a --export 9999 | sudo apt-key add -

Works fine here so far, use at your own risk.

Adding an “X-label” header to lots of messages at once using mutt

January 22nd, 2009

I’m using this method to add labels to individual messages in mutt. (You can use the X-label header in a similar way that you label e-mail in Gmail. You can search for messages with a certain label using the ~y pattern in mutt). But what if you suddenly want to apply a label to lots of messages in a mailbox?

If your original messages are in an “mbox” format mailbox, you can pipe the messages to formail, which adds the header, and append the messages to the current mailbox (let’s assume it’s called “mycurrentmbox”:

formail -I "X-label: yourlabel" >> mycurrentmbox

Note that this will remove any other “X-label” headers, if present. Alternatively, you might want to check out the -a or -i options (man formail).

I have my mail in “maildir” format, where each mail is an individual file. I use a workaround: pipe all messages to formail, which adds the header, then append to a temporary “mbox” format, delete the original messages in the maildir, then move the messages from the temporary mbox to the original maildir.

In your original maildir, tag and pipe-message, then:

formail -I "X-label: yourlabel" >> mytempmbox

Optionally check that the labeled messages have arrived safely in your temporary mailbox, delete all the tagged (unlabeled) original messages, then go to your temporary mailbox with

mutt -f mytempmbox

tag all messages there, save tagged to the original mailbox. Delete the temporary mailbox.

Filename pattern matching via bash extended globbing and find regular expressions in shell scripts

January 20th, 2009

I was confused that bash would expand some patterns nicely to match filenames when I was on the commandline, but the same pattern would not work from inside a shell script. For example, the following pattern would nicely match all files in the current directory not having an “Rnw” or “tex” extension on the commandline:

ls *.!(Rnw|tex)

Run from a shell script, however, this would give the error:

line 5: syntax error near unexpected token `('

It turns out on ubuntu, the shell option extglob is set for an interactive shell, but not for the non-interactive shell that is used when you run a script. You can see whether “extglob” is on like this, either from a commandline or by putting the line into your script:

shopt extglob

If it’s off and you want it on, put into your script:

shopt -s extglob

An alternative (that you might not want, I’m not sure what else it might affect) is to change the opening line of your script to read

#!/bin/bash -i

This runs your script in an interactive shell and should thus have the same behavior as the commandline. Generally, a neat trick is to use the -x option to debug shell scripts:

#!/bin/bash -x

An alternative way to get files whose names match a certain pattern is of course to use find. Here, you can either use limited globbing patterns with the -name option, and combine several patterns using -o, like this:

find . -name "*.tex" -o -name "*.txt"

Find also has a -regex option. If you use that, you probably want to use -regex-type=posix-extended to get a behavior that is more similar to extended regular expressions that you might know, for example from sed. Additionally, you have to watch out that find needs the regular expression to match the entire filename including the directory. Here is an example for this:

audrey:~/tmp/testdir$ ls
blah.tex  blah.txt
audrey:~/tmp/testdir$ find . -regex "blah\.tex"
audrey:~/tmp/testdir$ find . -regex "\./blah\.tex"
./blah.tex

Here is an example for the difference between the default and the extended regex pattern behavior:

audrey:~/tmp/testdir$ find . -regex "\./blah\.(tex|txt)"

finds nothing, but:

audrey:~/tmp/testdir$ find . -regextype posix-extended -regex "\./blah\.(tex|txt)"
./blah.tex
./blah.txt

You could alternatively get the desired behavior with the default regex by escaping the grouping parentheses and the “|” operator:

audrey:~/tmp/testdir$ find . -regex "\./blah\.\(tex\|txt\)"
./blah.tex
./blah.txt

But that starts getting really hard to read.

Removing duplicate lines from a file

January 14th, 2009

Case-insensitive:

{ rm "$file" && awk '!x[tolower($1)]++' > "$file"; } < "$file"

Case-sensitive:

{ rm "$file" && awk '!x[$1]++' > "$file"; } < "$file"

Here's a shell script you could use, as it stands, only works for one file at a time:

#!/bin/bash                                                                                  
                                                                                             
usage()                                                                                      
{                                                                                            
cat << EOF                                                                                   
                                                                                             
usage: $(basename $0) options filename                                                       
                                                                                             
Removes duplicates from a file                                                               
                                                                                             
OPTIONS:                                                                                     
   -h      Show this message                                                                 
   -i      case insensitive                                                                  
EOF                                                                                          
               }                                                                             
                                                                                             
insensitive="no"                                                                             
                                                                                             
while getopts "hi" option; do                                                                
    case $option in                                                                          
        h)                                                                                   
            usage  ; exit 0                                                               
            ;;                                                                               
        i)                                                                                   
            insensitive="yes"                                                                
            ;;                                                                               
        "")                                                                                  
            usage ; exit 1
            ;;                                                                               
        *)                                                                                   
            usage  ; exit 1
            ;;                                                                               
    esac                                                                                     
done                                                                                         
                                                                                             
shift $(($OPTIND - 1))                                                                       
                                                                                             
filename="$1"                                                                                
                                                                                             
if [ "$filename" == "" ] ; then                                                              
    usage ; exit 1                                                                           
elif [ ! -f "$filename" ] ; then                                                             
    echo "File $filename does not exist" ; exit 1                                            
fi                                                                                           

# make a backup                                                                              
cp "$filename" "$filename"~                                                                  
                                                                                             
if [ $insensitive == "yes" ] ; then                                                          
    { rm "$filename" && awk '!x[tolower($1)]++' > "$filename"; } < "$filename"               
else                                                                                         
    { rm "$filename" && awk '!x[$1]++' > "$filename"; } < "$filename"                        
fi

Here's some nice concise information about getopts and shift.

Edimax EW-7318USg and switch to wicd

January 11th, 2009

I’ve just bought the Edimax EW-7318USg wireless USB dongle, mainly to use it in corners of the house where the wireless signal is weak. It works fine and does seem to boost the signal.

With network-manager, I found no way to quickly switch between the built-in wireless card and the Edimax. I installed wicd, which uninstalls network-manager if you install it via aptitude (you have to add the repository first, see the wicd website). I like it so far. It seems more transparent in what it does than network-manager. You can manually enter an interface to use for wired or wireless. The Edimax shows up as “wlan0”, if I enter that, it connects via that, else, use the default “ath0”.

It seems I can also quickly put the Edimax into monitor mode via airmon-ng, but I haven’t done anything but watch it collect some packets in wireshark so far.