diff --git a/releng.control/cleanupArtifacts.sh b/releng.control/cleanupArtifacts.sh
index d89644f9d64f2f8b60a58c3c69ee5bbf41523f30..acb5d314be42e3e719bb5192dee6b9dc1a7ae450 100644
--- a/releng.control/cleanupArtifacts.sh
+++ b/releng.control/cleanupArtifacts.sh
@@ -10,30 +10,118 @@ then
    source ${RELENG_CONTROL}/commonComputedVariables.shsource
 fi
 
-# remove artifacts over n days old
+# remove directories over n days old
 # (where hours = 24 + (n * 24), basically, so that
 # even n=0 means "1 day")
 
-# set at 10 days, under assumption that before that time,
-# artifacts will be "saved" elsewhere, if needed.
-# if more cleanup is needed, we should take time, and
-# existence of more recent builds into account, so we never
-# delete the last existing build (even if "old").
+# set at ndays, under assumption that before that time,
+# direcotory will be "saved" elsewhere, if needed.
+# We never delete the last existing build (even if "old").
 
-ndays=4;
-artifactsDir=${PROJECT_ARTIFACTS};
+
+
+# requires parent Directiory as first argument
+# if nDays not specified as second argument, then 0 is assumed 
+#    (which is one day)
+# if "saveAtLeast" is not set, as third argument, then assumed to be 1
+#    (that is, at least "saveAtLeast" directories will be saved, no matter how old)
+function removeOldArtifactsDirectories () {
+
+parentDir=$1;
+ndays=$2;
+saveAtLeast=$3;
+
+if [ -z $parentDir ]
+then
+   echo "ERROR: no parent directory specified in function call";
+   return -1;
+fi  
+
+if [ -z ndays ] 
+then 
+   echo "INFO: ndays not specified, 1 day assumed";
+   ndays=0
+else 
+   echo "INFO: ndays set to $ndays";   
+fi
+
+if [ -z saveAtLeast ] 
+then 
+   echo "INFO: saveAtLeast not specified, 1 assumed";
+   saveAtLeast=0
+else 
+   echo "INFO: saveAtLeast set to $saveAtLeast";   
+fi
 
 echo;
-echo "    Removing artifact directories older than ${ndays} days";
-echo "        (from ${artifactsDir})";
-before=`find ${artifactsDir} -mindepth 2 -maxdepth 2 | wc -l`;
+echo "    Removing directories older than ${ndays} days";
+echo "        (from under ${parentDir})";
+before=`find ${parentDir} -mindepth 2 -maxdepth 2 | wc -l`;
 echo "            number of directories before cleaning: ${before}";
 
 # empty directories often result from "bad builds". We remove those no matter how old
-find ${artifactsDir} -mindepth 2 -maxdepth 3 -type d -empty -exec rm -fr '{}' \;
+find ${parentDir} -mindepth 2 -maxdepth 3 -type d -empty -exec rm -fr '{}' \;
 # now remove old ones
-find ${artifactsDir} -mindepth 2 -maxdepth 2 -type d -ctime +$ndays -execdir ${RELENG_CONTROL}/removeIf.sh '{}' \;
+find ${parentDir} -mindepth 2 -maxdepth 2 -type d -ctime +$ndays -execdir ${RELENG_CONTROL}/removeIf.sh '{}' $saveAtLeast \;
 
-after=`find ${artifactsDir} -mindepth 2 -maxdepth 2 | wc -l`;
+after=`find ${parentDir} -mindepth 2 -maxdepth 2 | wc -l`;
 echo "            number of directories after cleaning: ${after}";
-echo
+echo;
+
+}
+
+# requires parent Directiory as first argument
+# if nDays not specified as second argument, then 0 is assumed 
+#    (which is one day)
+# if "saveAtLeast" is not set, as third argument, then assumed to be 1
+#    (that is, at least "saveAtLeast" directories will be saved, no matter how old)
+function removeOldArtifactsDirectories () {
+
+parentDir=$1;
+ndays=$2;
+saveAtLeast=$3;
+
+if [ -z $parentDir ]
+then
+   echo "ERROR: no parent directory specified in function call";
+   return -1;
+fi  
+
+if [ -z ndays ] 
+then 
+   echo "INFO: ndays not specified, 1 day assumed";
+   ndays=0
+else 
+   echo "INFO: ndays set to $ndays";   
+fi
+
+if [ -z saveAtLeast ] 
+then 
+   echo "INFO: saveAtLeast not specified, 1 assumed";
+   saveAtLeast=0
+else 
+   echo "INFO: saveAtLeast set to $saveAtLeast";   
+fi
+
+echo;
+echo "    Removing directories older than ${ndays} days";
+echo "        (from under ${parentDir})";
+before=`find ${parentDir} -mindepth 1 -maxdepth 1 | wc -l`;
+echo "            number of directories before cleaning: ${before}";
+
+# empty directories often result from "bad builds". We remove those no matter how old
+find ${parentDir} -mindepth 1 -maxdepth 1 -type d -empty -exec rm -fr '{}' \;
+# now remove old ones
+find ${parentDir} -mindepth 1 -maxdepth 1 -type d -ctime +$ndays -execdir ${RELENG_CONTROL}/removeIf.sh '{}' $saveAtLeast \;
+
+after=`find ${parentDir} -mindepth 1 -maxdepth 1 | wc -l`;
+echo "            number of directories after cleaning: ${after}";
+echo;
+
+}
+
+
+removeOldArtifactsDirectories ${PROJECT_ARTIFACTS} 3 1;
+removeOldDirectories ${PROJECT_PROJECTS}  1 0;
+removeOldDirectories ${PROJECT_TESTS} 1 0;
+ 
diff --git a/releng.control/removeIf.sh b/releng.control/removeIf.sh
index a91f110be013a6cc95c7d967b35338227f35b9d8..db8fe8beb10095377d9bbce6ac8a2457dca2bddc 100644
--- a/releng.control/removeIf.sh
+++ b/releng.control/removeIf.sh
@@ -7,8 +7,14 @@ if [ -z $1 ]
     echo "  This script requires an argument. " ;
     exit 1;
   fi
-
 foundDirectory=$1
+nSave=$2
+
+if [ -z $nSave ]
+then
+   nSave=1;
+fi   
+
 # should already be in foundDirectory, if execDir used
 cd $foundDirectory
 # move up one so we can examine syblings
@@ -20,7 +26,7 @@ ndirs=$(($ndirs - 1)); # don't count the "totals" line
 # echo "NDirs: $ndirs"
 
 # if only one left, do not remove it, no matter how old
-if [ $ndirs -eq 1 ]
+if [ $ndirs -le $nSave ]
 then
     exit 0;
 fi
@@ -35,18 +41,8 @@ fi
 # adding a few "should never happen" errror checks
 if [ -d $foundDirectory ] 
 then
-  basedirname=$(basename $foundDirectory)
-  if [[ "$basedirname" =~ [[:digit:]]{14} ]]
-    then
-       echo "removing $basedirname"
-       rm -fr $foundDirectory
-    else
-     # patches is expected, warn of others
-      if [ "patches" != $foundDirectory ]
-       then 
-         echo "ERROR: The foundDirectory, $foundDirectory, didn't match timestamp pattern"
-       fi 
-    fi
+  rm -fr $foundDirectory
+  echo "removed $foundDirectory";
 else
-    echo "ERROR: the foundDirectory, $foundDirectory, is not a directory"
+  echo "ERROR: the foundDirectory, $foundDirectory, is not a directory"
 fi