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 :

Renaming projects in XCode 4

Xcode – renaming project causes problem

On the Renaming of Xcode Projects

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s