25 November 2010

Shell script to back up SVN working copy changes

To copy items shown by svn status, one can use a simple script as following.

#!/bin/bash - 
set -o nounset                              # Treat unset variables as an error

# Displays the message, usage info and exits with error code 1
function my_usage()
{
    msg=$1
    [[ $msg ]] && echo $msg
    echo "Usage:
    ./$0 source_dir destination_dir
    source_dir          Source directory
    destination_dir         Destination directory"
    exit 1
}

# Returns dir name with trailing slash
function my_get_dirname()
{
    dir=$1
    if [[ ${dir:${#dir}-1:1} != '/' ]]; then 
        dir=$dir"/"
    fi
    echo $dir
}

src_dir=`my_get_dirname $1`
dst_dir=`my_get_dirname $2`
verbose=1

# Validate args
if [[ ! -d $src_dir ]]; then 
    usage "'$src_dir' is not a directory"
elif [[ ! -d $dst_dir  ]]; then 
    usage "'$dst_dir' is not a directory"
fi

# Remember current dir 
dir=`pwd`
cd $src_dir

# Loop through files and folders 
svn st | awk '{ print $2 }' | while read F
do
    if [[ $F != 'framework' ]]; then
        # Create directory, if not exists
        d=`dirname "$dst_dir$F"`
        if [[ ! -d $d ]]; then 
            mkdir -p "$d"
        fi

        # Copy file or directory
        if [[ -f $F ]]; then
            [[ $verbose = 1 ]] && echo "FILE $F"
            cp -f "$F" "$dst_dir$F"
        elif [[ -d $F ]]; then
            [[ $verbose = 1 ]] && echo "DIR $F"
            [[ ! -d "$dst_dir$F" ]] && mkdir -p "$dst_dir$F"
            cp -rf $F $dst_dir$F/../
        fi
    fi
done

# Go to the initial dir 
cd $dir

# vim: set textwidth=80:softtabstop=4:tabstop=4:shiftwidth=4:
# vim: set expandtab:autoindent:

11 November 2010

Enable/Disable Apache virtual hosts on Ubuntu with Zenity

Here is a simple bash script I use to toggle virtual hosts in a GUI window.

#!/bin/bash
# get available & enables site names & set corresp-ly checkboxes in the following zenity list
vh_avail=(`ls -B /etc/apache2/sites-available/`);

i=0
s=""

while (( i< ${#vh_avail[*]} ))
do
 if [ -f /etc/apache2/sites-enabled/${vh_avail[$i]} ] ; then 
  s=$s"TRUE "
 else 
  s=$s"FALSE "
 fi
 s=$s${vh_avail[$i]}" "
 
 (( ++i ))
done

# get vhost name

vhosts=`(zenity --list --width=700 --height=500 --title="Choose vhost" \
 --checklist --column="" --column="vhost" $s)`;

case $? in 
 0) # OK
   a=(`echo "$vhosts"|tr "\|" " "`);
   i=0;
   di=0;
   
   #disable all
   
   while (( i< ${#vh_avail[*]} ))
   do
    if [ -f /etc/apache2/sites-enabled/${vh_avail[$i]} ] ; then 
     a2dissite ${vh_avail[$i]}
    fi
    (( ++i ))
   done
   
   # enable needed
   i=0;   
   while ((i < ${#a[*]}))
   do 
    if [ -f /etc/apache2/sites-available/${a[$i]} ] ; then
     a2ensite ${a[i++]}
    else
     (( di++ ))
    fi
   done 
   
   info="${#a[*]} vhosts enabled";
   
   if (( di>0 ));then
    info="$info\n$di vhosts not found in /etc/apache2/sites-available/"
    zenity --warning --text="$info"
   else 
    zenity --info --text="$info"
   fi
   
   # reload apache
   /etc/init.d/apache2 restart #reload not always works
  ;;
 1) # Cancel
  exit 0
  ;; 
esac
So you can make a desktop launcher with command
gksudo /share/scripts/bash/vhosts_ed.sh

06 November 2010

How to convert MP3 file tag encodings in Ubuntu

It was somewhat troublesome for me to convert ID3 tags for large amount of files, especially in case of file names, with spaces and other "special" characters. I found tools and managed to successfully convert Windows-1251 MP3 file tags to UTF-8. I also post a sample bash script here.

mp3info

This tool displays and modifies ID3 tags. Quite simple in use. I would deal with it, if there were no problems with long character sequences(just cuts unpredictably!).

mid3iconv

It's job is exactly what I want. Converts ID3 tag encodings to Unicode. Usage is simplisity itself, e.g.
$ mid3iconv -e "Windows-1251" ~/Music/sample.mp3

Sample bash script

So the task is to iterate each file and apply mid3iconv. But one should care files already having Unicode tags. Therefore, the following script tries to detect encoding by means of enca tool.

#!/bin/bash 
# Splits the first argument by delimeter specified by the 2nd parameter 
# E.g. my_split_str $string $delim
# If delimeter is not specified, the func defaults to '='
# Requirements: 
# enca
# mp3info
# python-mutagen (mid3iconv)
#
# Example: bash mp3id3enc.sh --from-code=Windows-1251 --to-code=UTF-8
function my_split_str()
{
    if (( $# <=1 )) 
    then 
        IFS='=' 
    else 
        IFS=$2 
    fi 
    set -- $1
    echo $*
}

function usage()
{
    echo $0" [options]"
    echo "Options:
    --src-dir       Source dir
    --auto-detect-enc       Whether try to auto detect source encoding. Default: 0
    --from-code     Source text encoding. Default: Windows-1251
    --to-code       Target text encoding. Default: UTF-8
    --guess-lang        Language to use when guessing source text encoding. Default: ru
    "
    exit 1
}

# Set option defaults
src_dir='./'                # source directory
auto_detect_enc=0           # auto detect source encoding
from_code='Windows-1251'
to_code='UTF-8'
guess_lang='ru'

# Get options
for i in $*
do
  o=(`my_split_str $i '='`)
  case ${o[0]} in
    --src-dir)
        src_dir=${o[1]}
        # Add trailing slash, if not added yet
        if [[ ${src_dir#${src_dir%?}} != '/' ]]; then src_dir=$src_dir"/"; fi
      ;;
    --from-code)
      from_code=${o[1]}
      ;;
    --to-code)
      to_code=${o[1]}
      ;;
    --guess-lang)
      guess_lang=${o[1]}
      ;;
    --auto-detect-enc)
      auto_detect_enc=1
      ;;
    --help)
        usage
        exit 1
      ;;
    *)
      # unknown option
      echo "Unknown option ${o[0]}"
      usage
      exit 2
      ;;
  esac
done

find "$src_dir" -name "*.mp3" | while read FILENAME
do
    echo "$FILENAME..."

    # Try to detect encoding
    if [[ $auto_detect_enc = 1 ]]; then
        e=`mp3info -p "%t" "$FILENAME" | enca -gL $guess_lang`

        if [[ "$e" = *1251* ]]; then 
            from_code="Windows-1251"
        elif [[ "$e" = *CP866* || "$e" = *866* ]]; then
            from_code="CP866"
        elif [[ "$e" = *KOI8-R* ]]; then
            from_code="KOI8-R"
        else
            echo "couldn't detect encoding for "$FILENAME
            echo "$FILENAME ($e)" >> not-detected.log 
            continue
        fi

        echo "detected encoding: "$from_code
    fi

    t=`mp3info -p "%t" "$FILENAME" | enca -L ru`

    # For unrecognized encoding assume Windows-1251 
    if [[ $t = *Unrecognized* ]]; then 
        t="Windows-1251"
    fi
    echo "t='$t'"
    if [[ $t != *866* && $t != *1251* ]]; then 
        echo "$FILENAME skipped"
        continue
    fi

    mid3iconv -e "$from_code" "$FILENAME"

    echo
done
Notice, loop like

for FILENAME in $(find $src_dir -name "*.mp3"); do
...
done
fails with file names containing spaces and other escape sequences.