Tuesday, January 26, 2010

Shell script for changing the interpreter in other scripts

For changing the first line in an interpreted script, the hash-bang (#!) line.

To get the most up to date version, download here.

#!/bin/bash
# Copyright (c) 2010 Sean A.O. Harney
#
# set-interpreter.sh
#
# Usage: set-interpreter.sh <new interpreter> <script file>
#
# Examples: ./set-interpreter.sh /usr/local/bin/omf file.omf
# ./set-interpreter.sh "/bin/bash -r" myshellscript.sh
#
# In the second example above the first line of myshellscript.sh
# would become the following: #!/bin/bash -r
#
# Yes, there is probably a way to do this in sed with one line.
#
#
# To set the first line of all files ending with .omf to #!/bin/omf run the following cmd:
#
# find . -name "*\.omf" -exec ./set-interpreter.sh /bin/omf {} \; ;
#


if [ $# -ne 2 ] ; then
echo -e "Usage:\t$0 <new interpreter> <script file>";
exit 1 ;
fi

NEW_INTERP="$1" ;
SCRIPT_FILE="$2" ;

if [ ! -r "${SCRIPT_FILE}" ] ; then
echo "Cannot proceed, ${SCRIPT_FILE} either does not exist or is not readable." ;
exit 1 ;
fi

FIRST_LINE=`head -n 1 "${SCRIPT_FILE}"` ;

if [[ ! "${FIRST_LINE}" =~ \#!.* ]] ; then
echo "Cannot proceed, ${SCRIPT_FILE} is not a valid script. It does not start with hash-bang (#!)." ;
echo "${SCRIPT_FILE} has not been modified." ;
exit 1 ;
fi

NEW_FIRST_LINE="#!${NEW_INTERP}" ; # Add the pound-hash.

if [ "${FIRST_LINE}" == "${NEW_FIRST_LINE}" ] ; then
echo "Cannot proceed, ${SCRIPT_FILE} already contains the desired new first line." ;
echo "${SCRIPT_FILE} has not been modified." ;
exit 1 ;
fi


TMP_FILE=`mktemp` ;
if [ $? -ne 0 ] ; then
echo "Cannot proceed, the mktemp program has failed." ;
echo "${SCRIPT_FILE} has not been modified." ;
exit 1 ;
fi


echo "${NEW_FIRST_LINE}" > "${TMP_FILE}" ;
tail --lines=+2 "${SCRIPT_FILE}" >> "${TMP_FILE}" ; # everything but the first line.

if [[ `cat "${TMP_FILE}" | wc -l` -ne `cat "${SCRIPT_FILE}" | wc -l` ]] ; then
echo "Cannot proceed, ${TMP_FILE} does not have the same line-count as ${SCRIPT_FILE} . Something went wrong." ;
echo "${SCRIPT_FILE} has not been modified." ;
exit 1 ;
fi

BAK_FILE="${SCRIPT_FILE}.bak" ;
while [ -e "${BAK_FILE}" ]
do
BAK_FILE="${BAK_FILE}.bak" ; # file.bak , file.bak.bak etc.
done

cp -b "${SCRIPT_FILE}" "${BAK_FILE}" ;
echo "Backed up ${SCRIPT_FILE} to ${BAK_FILE} . Preserved timestamps." ;

cat "${TMP_FILE}" > "${SCRIPT_FILE}" ; # better than mv since the $SCRIPT_FILE permissions et al will be preserved.
rm -f "${TMP_FILE}" ;
echo "Changed ${FIRST_LINE} to ${NEW_FIRST_LINE}" ;
echo "${SCRIPT_FILE} has been successfully modified." ;
exit 0 ;

No comments:

Post a Comment