diff --git a/bin/utils b/bin/utils
index 9f6ecb0399d5244d4d4acbfefe3eb739d30dac2d..742cd1cf356485300259b81a640f31a3c7a3be64 100755
--- a/bin/utils
+++ b/bin/utils
@@ -17,49 +17,59 @@ cleanup() {
 }
 
 # Buildpack Steps.
-function puts-step (){
+puts-step() {
   echo "-----> $@"
 }
 
 # Buildpack Warnings.
-function puts-warn (){
+puts-warn() {
   echo " !     $@"
 }
 
 # Usage: $ set-env key value
-function set-env (){
+set-env() {
   echo "export $1=$2" >> $PROFILE_PATH
 }
 
 # Usage: $ set-default-env key value
-function set-default-env (){
+set-default-env() {
   echo "export $1=\${$1:-$2}" >> $PROFILE_PATH
 }
 
 # Usage: $ set-default-env key value
-function un-set-env (){
+un-set-env() {
   echo "unset $1" >> $PROFILE_PATH
 }
 
 # Does some serious copying.
-function deep-cp (){
-  find -H $1 -maxdepth 1 -name '.*' -a \( -type d -o -type f -o -type l \) -exec cp -a '{}' $2 \;
-  cp -r $1/!(tmp) $2
-  # echo copying $1 to $2
+deep-cp() {
+  declare source="$1" target="$2"
+
+  mkdir -p "$target"
+
+  # cp doesn't like being called without source params,
+  # so make sure they expand to something first.
+  # subshell to avoid surprising caller with shopts.
+  (
+    shopt -s nullglob dotglob
+    set -- "$source"/!(tmp|.|..)
+    [[ $# == 0 ]] || cp -a "$@" "$target"
+  )
 }
 
 # Does some serious moving.
-function deep-mv (){
-  deep-cp $1 $2
-
-  rm -fr $1/!(tmp)
-  find -H $1 -maxdepth 1 -name '.*' -a \( -type d -o -type f -o -type l \) -exec rm -fr '{}' \;
+deep-mv() {
+  deep-cp "$1" "$2"
+  deep-rm "$1"
 }
 
 # Does some serious deleting.
-function deep-rm (){
-  rm -fr $1/!(tmp)
-  find -H $1 -maxdepth 1 -name '.*' -a \( -type d -o -type f -o -type l \) -exec rm -fr '{}' \;
+deep-rm() {
+  # subshell to avoid surprising caller with shopts.
+  (
+    shopt -s dotglob
+    rm -rf "$1"/!(tmp|.|..)
+  )
 }