Delete or Move Revit Backups

, , ,
Delete Backups GIF

Removing Revit backups for families and project files can be, sometimes, a bit tedious. If you have folders and subfolders with tons of families or not work shared projects, backups can take a big portion of the storage and make it hard to find what you need.

The first option we have to address this issue is to do a manual search in the parent folder for backup files and move or delete them. The second option is to create a script to do it with just a click. And as you can imagine, I will favor this approach as we can have some fun programming our own tool.

Without further delay, here is a preview:

The script is quite simple, three input nodes and a Python script. The three nodes under INPUT allow the user to choose options in Dynamo Player. Don´t forget to select the node and set it as Is Input, otherwise, it will not show in Dynamo player.

The beautiful part comes inside the Python script:

# Import sys module and assign the right path for the IronPython Library
import sys
sys.path.append(r"C:\Program Files (x86)\IronPython 2.7\Lib")
# Import os module to get directories
import os
# Import re module to match file extensions
import re
# Import shutil module to move files
import shutil

# The inputs to this node will be stored as a list in the IN variables.
directory = IN[0]
delMov = IN[1]
backupDir = IN[2]
# Empty list to store the filenames that have been removed or moved
modFiles = list()

# Function to clean the backup files
def directoryClean():

	# Collect all files in directory and subdirectories
	for folderName, subFolders, files in os.walk(directory):
		# Pattern to check against if file is a revit family or project backup
		matchBackups = re.compile(r'.*\.\d+.r(vt|fa)$')

		# Loop over the files
		for file in files:
			# Assign the matched files to a variable
			matched =

			# If the file is a match
			if matched:
				# Get the original filepath for the file
				filePath = os.path.join(folderName, file)
				# Get the destination filepath for the file
				backupPath = os.path.join(backupDir, file)
				# Change matched files permission to writable
				os.chmod(filePath, 436)
				# Append modified elements to modFiles list

				# Case False: Move backup files
				if delMov == False:
					# Move matched files
					shutil.move(filePath, backupPath)

				# Case True: Delete backup files
					# Delete matched files

# Call the function to execute

#Assign your output to the OUT variable.
OUT = modFiles

Lines 1-9: import modules from the IronPython library. The first import is sys, which we use to fix the path to the library of IronPython. At least in my case, the library path pointed to another directory and I couldn´t load the modules. By the way, modules are code that other more talented programmers have already done for us! Bless them!

We could have done all the imports in the same line as:

import sys, os, re, shutil

However, for clarity and educational purpose, I have chosen not to.

Lines 11-14: variables that store the inputs from Dynamo. The number must match the number of INs in the Python script node.

Lines 20-46: Here comes the fun! It is the definition of the function that will do the job.

Line 22: uses os.walk to go through and search for all subfolders and files in folderName (that´s the variable where is stored the directory of our library)

Line 24: uses re.compile to establish the pattern to match. The module re is the Regular Expression module and I will explain it in more detail. Compile takes a string as argument, so in r’.*\.\d+.r(vt|fa)$’

 .* is match any character

.\d+ is match . (dot) + at least one digit

.r(vt|fa) is match . (dot) followed by r and vt or fa

$ means that the name must end in that order. It is redundant in this case, as any backup will follow the regex pattern, but I think is not a bad idea in case we add groups to the regex expression down the line to expand the script.

Line 28: assigns to the variable matched the matched regex object (not a string with the path yet) to filter later only the matched files.

Line 36: this line of code is one of the reasons to choose the Python script over conventional nodes. It changes the writing permission of the file, if a file is read-only, Dynamo won´t be able to modify it and neither Python. But as far as I know, it is not possible to set file permissions in Dynamo. Here´s a comprehensive list, but being honest, I don’t have the time to go through all of them, tested that 436 does its job.

Lines 44 and 46: use the module imported at the beginning to move or remove the filtered files.

Line 49: calls the function into action. Functions don´t execute until you call or invoke them.

And finally, in line 52, we output the list of cleaned files.

So, work done!

Here is the whole script:

Hit Run or Play and enjoy a library free of backup files!

Leave a Reply

Your email address will not be published. Required fields are marked *