====== 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
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-Builder((i.e. WindowsCE builds)) 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 [[http://sourceforge.net/projects/pywin32/|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