User Tools

Site Tools


coding:utilities

This is an old revision of the document!


Utilities

A collection of scripts and the like which I have come to rely on.

BASH shell

Red STDERR

Runs the command given, but colours STDERR red, making it easier to spot problems when there is a lot of output. Particularly useful with “make” commands.

# Red STDERR
# rse <command string>
function rse()
{
        # We need to wrap each phrase of the command in quotes to preserve arguments that contain whitespace
        # Execute the command, swap STDOUT and STDERR, colour STDOUT, swap back
        ((eval $(for phrase in "$@"; do echo -n "'$phrase' "; done)) 3>&1 1>&2 2>&3 | sed -e "s/^\(.*\)$/\1/") 3>&1 1>&2 2>&3
}
export -f rse # Export function, so it is available to subshells

Examples:

rse find /etc -iname \*.conf

...
/etc/debconf.conf
/etc/ca-certificates.conf
/etc/gssapi_mech.conf
find: /etc/ssl/private: Permission denied
/etc/pam.conf
/etc/nsswitch.conf
/etc/sestatus.conf
...

Multi-Move

Allows renaming of multiple files using pattern matching.

# Multi-Move
# mm [file list/glob] [regexp match] [regexp replace]
function mm
{
        [ "$#" -eq 0 ] && echo "mm [file list/glob] [regexp match] [regexp replace]" >&2 && return
        for file in $1; do mv "$file" "$(echo $file | sed -e "s/$2/$3/")"; done
}
export -f mm

Example:

# Files before:
$ ls
1.dat  1.txt  10.txt  2.dat  2.txt  3.dat  3.txt  4.dat  4.txt  5.txt  6.txt  7.txt  8.txt  9.txt
 
# Rename *.txt -> *.txt.bak
$ mm '*.txt' '.txt' '.txt.bak'
 
# Files after:
$ ls
1.dat  1.txt.bak  10.txt.bak  2.dat  2.txt.bak  3.dat  3.txt.bak  4.dat  4.txt.bak  5.txt.bak  6.txt.bak  7.txt.bak  8.txt.bak  9.txt.bak
# Files before:
$ ls
a_1.html  a_2.html  a_3.html  b_1.html  b_2.html  b_3.html  c_1.html  c_2.html  c_3.html
a_1.txt   a_2.txt   a_3.txt   b_1.txt   b_2.txt   b_3.txt   c_1.txt   c_2.txt   c_3.txt
 
# Pad numbers with zeros
# Use escaped parenthesis to capture one or more characters in the range 0-9, and replace them with "0" + "previous contents"
$ mm '*' '\([0-9]\+\)' '0\1'
 
# Files after:
$ ls
a_01.html  a_02.html  a_03.html  b_01.html  b_02.html  b_03.html  c_01.html  c_02.html  c_03.html
a_01.txt   a_02.txt   a_03.txt   b_01.txt   b_02.txt   b_03.txt   c_01.txt   c_02.txt   c_03.txt

Generate Cscope database

Creates a cscope database for the current directory, suitable for use with a vim which has been compiled with +cscope.

#!/bin/bash
echo Creating file list...
find `pwd` "$@" -name \*.c -o -name \*.h -o -name \*.cpp -o -iname Makefile -o -name \*.mak | sed -e 's/^/"/g' -e 's/$/"/g'> cscope.files
echo Building database...
cscope -b -q
echo Done

Propagate RC files

Simple script to push my config files from the current host to all others in my list

#!/bin/bash
 
# Copies local .vimrc, .screenrc and other settings to all my other accounts
# TODO: Possibly account for my tablet PC, which isn't always on
 
cd ~
FILELIST="
    .vimrc
    .screenrc
    .bashrc
    .bash_profile
    editor.sh
    less.sh
    propagate_rc_files.sh
    .vim
"
if [ $# -gt 0 ]; then
    HOSTLIST="$@"
else
    HOSTLIST="
        meermanr@ikari.robmeerman.co.uk:
        meermanr@ryoga.robmeerman.co.uk:
        meermanr@ryo-ohki.robmeerman.co.uk:
    "
fi
 
function IPof()
{
    # POSIX
    if [ -x "$(which traceroute 2>/dev/null)" ]; then
        traceroute -m 1 -w 2 $1 2>&1 \
        | head -n1 \
        | cut -d " " -f 4 \
        | tr -d "(),"
 
    # Windows (Cygwin)
    elif [ -x "$(which tracert 2>/dev/null)" ]; then
        tracert -h 1 -w 1 $1 \
        | head -n2 \
        | tail -n1 \
        | cut -d " " -f 5 \
        | tr -d "[]\015"        # Snip ^M off the end, stupid Windows<->Cygwin interworking!
 
    fi
}
 
# Find local IP
if [ -x "/sbin/ifconfig" ]; then
    LOCAL_IP=$(/sbin/ifconfig | head -n2 | tail -n1 | sed -e 's/^[^0-9]\+//' | cut -d ' ' -f1)
elif [ -x "/cygdrive/c/WINDOWS/system32/ipconfig" ]; then
    LOCAL_IP=$(ipconfig | grep -C3 "Local Area Connection" | grep "IP Address" | tail -n1 | cut -d : -f 2 | sed -e 's/\s\+\(\S\+\)\s\+/\1/')
else
    LOCAL_IP=""
fi
 
echo LOCAL_IP = \"$LOCAL_IP\"
 
for HOST in $HOSTLIST; do
    TARGET_HOST=$(echo $HOST | cut -d '@' -f2 | cut -d ':' -f1)
    TARGET_IP=$( IPof $TARGET_HOST )        # Function call
    echo $TARGET_HOST = \"$TARGET_IP\"
    [ "$LOCAL_IP" = "$TARGET_IP" ] && echo "Skipping..." && continue
    [ "127.0.1.1" = "$TARGET_IP" ] && echo "Skipping..." && continue
 
    echo Uploading to $HOST
    scp -r ${FILELIST} $HOST
    echo ___
    echo
done

pb

Runs a command in a Microsoft Platform Builder environment.

#!/usr/bin/bash
# vim: set ft=sh:
 
# Runs a command in a Microsoft Windows CE Platform Builder environment
 
 
 
# If you don't have a buildenv.bat you can create one by running
#
#   pbxmlutils /getbuildenv > ../../buildenv.bat
#
# from inside a build window (Visual Studio -> Build -> Open Release Directory
# in Build Window).
 
 
 
# Note the parenthesis below, all commands inside them are run in a
# sub-shell, which prevents the export polluting the current shell
(
 
    PB_BUILDENV_BAT=/cygdrive/c/WINCE600/OSDesigns/mwin/WINCE600/OSDesigns/mali-win-ebmpcore/buildenv.bat
 
    # Convert all "set" commands in $PB_BUILDENV_BAT to "export" commands,
    # and evaluate them (updating this sub-shell's environment)
    eval \
        $( grep '^set' $PB_BUILDENV_BAT \
            | sed \
                -e 's/^set /export /' \
                -e 's/=/="/' \
                -e 's/$/"/' \
                -e 's/\\/\\\\/g' \
        )
 
    # Convert paths in $PATH from Win32 style ("c:\foo;c:\bar") to  Cygwin
    # style ("/cygdrive/c/foo:/cygrive/c/bar) using the `cygpath` utility
    # NB: Must use absolute paths here, because the effective $PATH is trashed!
    eval \
        $( echo export PATH=\"$PATH\" \
            | /usr/bin/sed -e 's/;/\n/g' \
            | /usr/bin/xargs --delimiter="\n" /usr/bin/cygpath -u \
            | /usr/bin/tr "\n" ":"
        )
 
    # Run arguments in this altered sub-shell
    "$@"
)

Example:

# What happens without the "pb" command
$ build
-bash: build: command not found

# And with the "pb" command
$ pb build
/home/robmee01/usr/bin/pb: line 32: export: `WECVERSIONFORROSEBUD.1488=2': not a valid identifier
BUILD: [Thrd:Sequence:Type  ] Message
BUILD: [00:0000000000:PROGC ] Build started with parameters:
BUILD: [00:0000000001:PROGC ] Build started in directory: c:\work\WinCE\estimate_current_directory
...

mymake

Convenience script which picks the appropriate build method. Suited for use as a one-fire make command from vim. :set makeprg=~/usr/bin/mymake

Written primarily to allow me compile GNU-Make and Microsoft-Platform-Builder1) driven sources using a single command which works out which to call, and mangles the output from Platform Builder so it looks more like “traditional” compiler output which I vim can parse.

#!/usr/bin/bash
# Wrapper script to find the most appropriate build method depending on where
# it is called from
 
# Configure pre/post scripts
# Note that ":" is a BASH built-in which returns true (0)
if [ -r ./mymake-pre ]; then
    PREEXEC=./mymake-pre
else
    PREEXEC=:
fi
if [ -r ./mymake-post ]; then
    POSTEXEC=./mymake-post
else
    POSTEXEC=:
fi
 
if [ -e sources -o -e dirs ]; then
    # WindowsCE
    # Mangle the output so it resembles every other compiler on the planet,
    # and thus can be intepreted by decent text editors
    $PREEXEC && \
    pb build "$@" 2>&1 \
        | tr -d "\\015" \
        | grep -e "WARNN\\|ERRORE" \
        | sed -e "s@^.*] @@" -e "s@ : @:@" \
    && $POSTEXEC
    exit
fi
 
for filename in ./mymake ../mymake; do
    if [ -x $filename ]; then
        $PREEXEC && exec $filename "$@" && $POSTEXEC
    elif [ -r $filename ]; then
        $PREEXEC && source $filename "$@" && $POSTEXEC
        exit
    fi
done
 
if [ -e Makefile -o -e GNUMakefile ]; then
    $PREEXEC && make "$@" && $POSTEXEC
    exit
fi
 
echo "Don't know how to make this directory, sorry."

python-win

Runs a python script using the Win32 version of Python from within Cygwin. Only useful if you have both Cygwin-python and Win32-python installed on the same machine.

#!/usr/bin/bash
# Wrapper to allow shell scripts to be run using the Windows (not Cygwin) version of Python
# Specifically, translates the first argument into a Windows-friendly path, and hands-off to Python
SCRIPT=$1; shift
exec /cygdrive/c/Python25/python.exe $(cygpath -w "$SCRIPT") "$@"

dexplore-jump.py

Jump to a topic in the Microsoft Visual Studio 2005 Documentation explorer (dexplore.exe) via the command line. I wrote this so I could use vim's manpage-lookup feature when editing WindowsCE source code.

Hard-coded to only search within the documentation for “Windows CE 6.0”.

Note: This script requires Python's win32com module, which is part of Python for Windows extensions.

Note: dexplore.exe must already be running for this script to work. Code to start dexplore.exe if needed may be added later.

Note: This uses the python-win script (above) as the interpreter to ensure it is run using the Win32 installation of Python

#!/home/robmee01/usr/bin/python-win
# Jump to keyword in DExplore
# Huge thanks to Rob Chandler and his page http://www.helpware.net/mshelp2/dexplore/dexplorer.htm
import win32com.client, sys
h = win32com.client.Dispatch("DExplore.AppObj")
h = h.Help  # Probably not necessary
h.SetCollection("ms-help://MS.VSCC.v80/MS.VSIPCC.v80/MS.WindowsCE.v60.en", "Windows Embedded CE 6.0")
if sys.argv[1][0:10] == "ms-help://":
    h.DisplayTopicFromURL(sys.argv[1])
else:
    h.DisplayTopicFromKeyword(sys.argv[1])

Example:

# Jump to the topic "GetModuleFileName" in an existing instance of dexplore.exe
$ dexplore-jump.py GetModuleFileName
1)
i.e. WindowsCE builds
coding/utilities.1217507897.txt.gz · Last modified: 2011/03/01 16:19 (external edit)