CloneXcodeProject.sh
What
Programming with Xcode?
Want to make a fresh start from an existing Xcode project under a new name?
Not quite satisfied with project renaming features in Xcode 4.0?
Me too.
How
I have been using the excellent Monte Ohrt’s script renameXcodeProject.sh for almost 2 years, and I made small improvements along the way.
I named my version of the script cloneXcodeProject.sh to reflect more precisely what the scripts do : while Xcode renames things in place, these scripts make a copy of all project files and then rename the copied files and text items in them.
Sometimes you want to clone a project whose files are read-only (perhaps they were checked into a Perforce depot). In this case the copied files are also read-only, and Monte’s script can’t modify them. My script makes them writable.
Monte’s script refuses to work if the new project name contains the old name. You have to run his script twice in this case, first cloning to a temporary project name and then to the final name, and remove the temporary project at the end. I did this many times, until I looked for and found a simple automated solution.
If needed, my script creates the temporary clone and then launches itself recursively for the second pass in which it clones and then removes the temporary clone.
Here is my script :
#!/bin/sh
################################################################################
#
# cloneXcodeProject.sh
#
# morphed from the original renameXcodeProject.sh by Monte Ohrt (see below)
# by Rudi Farkas <rudi.farkas@gmail.com>
# version : 1.01
# date : 22 Jul 2011
#
# purpose : copy and rename an XCode project
#
# features (over and above those of renameXcodeProject.sh) :
#
# 1- makes the copied files writable before attempting to modify their content
#
# 2- works even if the new project name contains the old project name, for instance
# cloneXcodeProject.sh "MyStuff" "MyStuff2"
#
# installation :
#
# copy this file to a directory in your PATH, and make it executable with :
#
# chmod +x cloneXcodeProject.sh
#
# usage :
#
# cloneXcodeProject.sh <OldProjectName> <NewProjectName>
#
# example :
#
# cloneXcodeProject.sh MyStuff MyNewStuff
#
# use at your own risk
# let me know if something does not work as advertized
#
################################################################################
################################################################################
#
# renameXcodeProject.sh
#
# author: Monte Ohrt <monte@ohrt.com>
# date: Jan 27, 2009
# version: 1.0
# http://www.phpinsider.com/xcode/renameXcodeProject.sh.txt
#
# This script will copy an xcode project to a new project directory name
# and replace/rename all files within to work as expected under the new name.
# Project names that contain characters other than alpha-numeric, spaces or
# underscores MAY not work properly with this script. Use at your own risk!
# Be CERTAIN to backup your project(s) before renaming.
#
# One simple rule:
#
# 1) The old project name cannot contain the new project name, so for instance,
# renaming "MyStuff" to "MyStuff2" will not work. If you really need to do
# this, rename the project to a temp name, then rename again.
#
# I have instructions for manually renaming an xcode project here:
#
# http://mohrt.blogspot.com/2008/12/renaming-xcode-project.html
#
#
# Installation:
#
# Copy (this) file "renameXcodeProject.sh" to your file system, and invoke:
#
# chmod 755 renameXcodeProject.sh
#
# to make it executable.
#
# usage:
#
# renameXcodeProject.sh <OldProjectName> <NewProjectName>
#
# example:
#
# ./renameXcodeProject.sh MyStuff MyNewStuff
#
################################################################################
OLDNAME=$1
NEWNAME=$2
# remove bad characters
OLDNAME=`echo "${OLDNAME}" | sed -e "s/[^a-zA-Z0-9_ -]//g"`
NEWNAME=`echo "${NEWNAME}" | sed -e "s/[^a-zA-Z0-9_ -]//g"`
echo ${OLDNAME}
echo ${NEWNAME}
TMPFILE=/tmp/xcodeRename.$$
TMPPROJNAME="D401CB997FCB4CB4AABFAC60E754C7B2"
if [ "$OLDNAME" = "" -o "$NEWNAME" = "" ]; then
echo "usage: $0 <OldProjectName> <NewProjectName>"
exit
fi
if [ ! -d "${OLDNAME}" ]; then
echo "ERROR: \"${OLDNAME}\" must be a directory"
exit
fi
# set new project directory
if [ -d "${NEWNAME}" ]; then
echo "ERROR: project directory \"${NEWNAME}\" exists. Terminating."
exit
fi
# does NEWNAME contain OLDNAME ?
echo "${NEWNAME}" | grep "${OLDNAME}" > /dev/null
if [ $? -eq 0 ]; then
# yes : set up names for the two-pass operation
FINALNAME="${NEWNAME}"
NEWNAME="401CB99D-7FCB-4CB4-AABF-AC60E754C7B2"
echo "Warning: New project name contains old project name. Project will be renamed in two passes."
else
# no : one pass operation is sufficient
FINALNAME=""
fi
# be sure tmp file is writable
cp /dev/null ${TMPFILE}
if [ $? -ne 0 ]; then
echo "tmp file ${TMPFILE} is not writable. Terminating."
exit
fi
# create project name with unscores for spaces
OLDNAMEUSCORE=`echo "${OLDNAME}" | sed -e "s/ /_/g"`
NEWNAMEUSCORE=`echo "${NEWNAME}" | sed -e "s/ /_/g"`
# copy project directory
echo copying project directory from "${OLDNAME}" to "${NEWNAME}"
cp -rp "${OLDNAME}" "${NEWNAME}"
# remove build directory
echo removing build directory from "${NEWNAME}"
rm -rf "${NEWNAME}/build"
# find text files, replace text
find "${NEWNAME}/." | while read currFile
do
# find files that are of type text
file "${currFile}" | grep "text" > /dev/null
if [ $? -eq 0 ]; then
# make sure it is writable
chmod +w "${currFile}"
# see if old proj name with underscores is in the text
grep "${OLDNAMEUSCORE}" "${currFile}" > /dev/null
if [ $? -eq 0 ]; then
# replace the text with new proj name
echo replacing "${OLDNAMEUSCORE}" in "${currFile}"
sed -e "s/${OLDNAMEUSCORE}/${NEWNAMEUSCORE}/g" "${currFile}" > ${TMPFILE}
mv ${TMPFILE} "${currFile}"
cp /dev/null ${TMPFILE}
fi
# see if old proj name is in the text
grep "${OLDNAME}" "${currFile}" > /dev/null
if [ $? -eq 0 ]; then
# replace the text with new proj name
echo replacing "${OLDNAME}" in "${currFile}"
sed -e "s/${OLDNAME}/${NEWNAME}/g" "${currFile}" > ${TMPFILE}
mv ${TMPFILE} "${currFile}"
cp /dev/null ${TMPFILE}
fi
fi
done
# rename directories with underscores
find "${NEWNAME}/." -type dir | while read currFile
do
echo "${currFile}" | grep "${OLDNAMEUSCORE}" > /dev/null
if [ $? -eq 0 ]; then
MOVETO=`echo "${currFile}" | sed -e "s/${OLDNAMEUSCORE}/${NEWNAMEUSCORE}/g"`
echo renaming "${currFile}" to "${MOVETO}"
mv "${currFile}" "${MOVETO}"
fi
done
# rename directories with spaces
find "${NEWNAME}/." -type dir | while read currFile
do
echo "${currFile}" | grep "${OLDNAME}" > /dev/null
if [ $? -eq 0 ]; then
MOVETO=`echo "${currFile}" | sed -e "s/${OLDNAME}/${NEWNAME}/g"`
echo renaming "${currFile}" to "${MOVETO}"
mv "${currFile}" "${MOVETO}"
fi
done
# rename files with underscores
find "${NEWNAME}/." -type file | while read currFile
do
echo "${currFile}" | grep "${OLDNAMEUSCORE}" > /dev/null
if [ $? -eq 0 ]; then
MOVETO=`echo "${currFile}" | sed -e "s/${OLDNAMEUSCORE}/${NEWNAMEUSCORE}/g"`
echo renaming "${currFile}" to "${MOVETO}"
mv "${currFile}" "${MOVETO}"
fi
done
# rename files with spaces
find "${NEWNAME}/." -type file | while read currFile
do
echo "${currFile}" | grep "${OLDNAME}" > /dev/null
if [ $? -eq 0 ]; then
MOVETO=`echo "${currFile}" | sed -e "s/${OLDNAME}/${NEWNAME}/g"`
echo renaming "${currFile}" to "${MOVETO}"
mv "${currFile}" "${MOVETO}"
fi
done
rm -f ${TMPFILE}
if [ "$FINALNAME" = "" ]; then
# this is the second pass : remove temp project directory
if [ "${OLDNAME}" = "${TMPPROJNAME}" ]; then
rm -rf "${TMPPROJNAME}"
fi
echo finished.
exit
else
echo
echo starting the second pass...
$0 "$NEWNAME" "$FINALNAME"
fi
Why
Googling for “Xcode 4 rename project” produces quite a few discussions and contrasting opinions, for example :
Xcode – renaming project causes problem
On the Renaming of Xcode Projects
leave a comment