# Config blender to save backup files in subfolder

Blender is by default config to save backup file from previous saves like .blender1, .blender2 and this is a good thing in case you mess up. What i want is to config blender to place this specific files in a subdirectory. Right now they show up in the list of blender files and make the list really long if you have a few scenes. Is it possible to config blender to do this?

Illustration of the structure.

.blender_folder
..Backup
...file1.blender1
...file1.blender2
...file2.blender1
...file2.blender2
..file1.blender
..file2.blender

• I don't think you can do this without altering the source code and building your own version. – sambler Feb 11 '14 at 8:59
• Make a request as it is a thing that bothers me a bit, too – WorldSEnder Feb 11 '14 at 20:22

I took a little time writing an addon for Blender, which will move the backup save files to a sub directory every time you save. You may change it however you want it to work.

I hope it works for you guys. :)

Simply save the code below into a file called something .py, I called mine "blender_move_backup_save_files_to_a_sub_directory.py".

Then import the file by clicking: File > User Preferences > Addons > Install From File... > Finally select the file and activate the addon.

bl_info = {
"version": (1, 3),
"blender": (2, 68, 0),
"name": "Move Backup Save Files To A Sub Directory",
"author": "Jonathan Stroem",
"description": """Move the backup save files to a sub-directory instead of the Blender-file's current directory. A new folder called "backup.blend" will be created and all save-files will be moved there instead of the default folder.""" ,
"category": "System",
"location": """The backup folder will be named "backup.blend". Under 'File > User Preferences > File > Save Versions', you can change how many backups that'll be used.""",
}

#IMPORTS
import bpy, os
import shutil
from bpy.app.handlers import persistent

import time
from stat import *

def register():
bpy.app.handlers.save_post.append(move_handler)

def unregister():
bpy.app.handlers.save_post.remove(move_handler)

#So that Blender recognize it as an addon.
if __name__ == "__main__":
register()

@persistent
def move_handler(dummy):

#fullpath = Full path to the data file.
#directory = Directory the data file is in.
#name = Name of file, without extension.
#extension = Extension of files.
#backup_amount = Max amount of backups to store.
#backup_directory = The name of the backup directory. (Where the files should be moved.) So change this if you want to change where the backups are saved.

file = {"fullpath":bpy.data.filepath, \
"directory":os.path.dirname(bpy.data.filepath), \
"name":bpy.path.display_name_from_filepath(bpy.data.filepath), \
"extension":".blend", \
"backup_amount":bpy.context.user_preferences.filepaths.save_version, \
"backup_directory":"backup.blend" \
}

#Create backup directory if it doesn't exist.
if file["backup_directory"] not in os.listdir(file["directory"]) :
os.chdir(file["directory"])
os.mkdir(file["backup_directory"])

#Get current save files from the backup directory.
currentFiles = []
for f in [ f for f in os.listdir(file["directory"] + "\\" + file["backup_directory"]) for c in range(1, int(file["backup_amount"]) + 1) if f == file["name"] + file["extension"] + str(c) if os.path.isfile(os.path.join(file["directory"] + "\\" + file["backup_directory"], f)) ] :
currentFiles.append(f)

#All this is moving the correct file.
if len(currentFiles) < 1 : #If no files, then no need to check.
if os.path.isfile(file["fullpath"] + "1") :
shutil.move(file["fullpath"] + "1", file["directory"] + "\\" + file["backup_directory"] + "\\" + file["name"] + ".blend1")
else : #If the max backup amount has been reached, then check for the oldest file and overwrite that one.
if file["backup_amount"] <= len(currentFiles) :
replaceFile = {"modified_date":None, \
"fullname":""}
for f in currentFiles :
stats = os.stat(file["directory"] + "\\" + file["backup_directory"] + "\\" + f) #Get attributes from a file.
if replaceFile["fullname"] == "" : #This will happen only the first time.
replaceFile["fullname"] = f
replaceFile["modified_date"] = time.asctime(time.localtime(stats[ST_MTIME]))
else : # Is the previous file older or newer? If it's older, then you'd want to overwrite that one instead. Go through all backup-files.
temp_modified = time.asctime(time.localtime(stats[ST_MTIME]))
if replaceFile["modified_date"] > temp_modified :
replaceFile["fullname"] = f
replaceFile["modified_date"] = temp_modified

#When the loop is finished, the oldest file has been found, and will be overwritten.
shutil.move(file["fullpath"] + "1", file["directory"] + "\\" + file["backup_directory"] + "\\" + replaceFile["fullname"])
else : #If the max backup amount hasn't been reached, and the folder isn't empty.
#Then check for the next number, and then just move the file over with the correct number.
replaceFile = "" #Location.
for f in currentFiles :
for c in range(1, int(file["backup_amount"]) + 1) :
if not os.path.isfile(file["directory"] + "\\" + file["backup_directory"] + "\\" + file["name"] + file["extension"] + str(c)) :
shutil.move(file["fullpath"] + "1", file["directory"] + "\\" + file["backup_directory"] + "\\" + file["name"] + file["extension"] + str(c))
replaceFile = f
break
if replaceFile != "" : #File to replace has been found, break out.
break


• Thanks for take the time to do this, is it ok if i spread the code to other people that might be interested? – Frozendragon Feb 13 '14 at 9:50
• You're welcome, I'm glad you like it.Yes, definitely! Feel free to spread it around. – Jonathan Feb 13 '14 at 17:25
• Even though this is 4 years old, it's still very useful. – Leander Jun 5 '18 at 9:35

First of all, thank you Jonathan for writing this script. I'm much happier with this arrangement of backup files!

It didn't work out of the box on my Mac because the some of the OS paths were constructed with hard-coded Windows backslashes, so I went in and changed them to be platform independent.

I hope this is helpful to someone. Since I hadn't seen any later versions of this script, I went ahead and advanced the version #.

bl_info = {
"version": (1, 4),
"blender": (2, 68, 0),
"name": "Move Backup Save Files To A Sub Directory",
"author": "Jonathan Stroem",
"description": """Move the backup save files to a sub-directory instead of the Blender-file's current directory. A new folder called "backup.blend" will be created and all save-files will be moved there instead of the default folder.""" ,
"category": "System",
"location": """The backup folder will be named "backup.blend". Under 'File > User Preferences > File > Save Versions', you can change how many backups that'll be used.""",
}

#IMPORTS
import bpy, os
import shutil
from bpy.app.handlers import persistent

import time
from stat import *

def register():
bpy.app.handlers.save_post.append(move_handler)

def unregister():
bpy.app.handlers.save_post.remove(move_handler)

#So that Blender recognize it as an addon.
if __name__ == "__main__":
register()

@persistent
def move_handler(dummy):

#fullpath = Full path to the data file.
#directory = Directory the data file is in.
#name = Name of file, without extension.
#extension = Extension of files.
#backup_amount = Max amount of backups to store.
#backup_directory = The name of the backup directory. (Where the files should be moved.) So change this if you want to change where the backups are saved.

file = {"fullpath":bpy.data.filepath, \
"directory":os.path.dirname(bpy.data.filepath), \
"name":bpy.path.display_name_from_filepath(bpy.data.filepath), \
"extension":".blend", \
"backup_amount":bpy.context.user_preferences.filepaths.save_version, \
"backup_directory":"backup.blend" \
}

#Create backup directory if it doesn't exist.
if file["backup_directory"] not in os.listdir(file["directory"]) :
os.chdir(file["directory"])
os.mkdir(file["backup_directory"])

#Get current save files from the backup directory.
currentFiles = []
for f in [ f for f in os.listdir(os.path.join(file["directory"], file["backup_directory"])) for c in range(1, int(file["backup_amount"]) + 1) if f == file["name"] + file["extension"] + str(c) if os.path.isfile(os.path.join(file["directory"], file["backup_directory"], f)) ] :
currentFiles.append(f)

#All this is moving the correct file.
if len(currentFiles) < 1 : #If no files, then no need to check.
if os.path.isfile(file["fullpath"] + "1") :
shutil.move(file["fullpath"] + "1", os.path.join(file["directory"], file["backup_directory"], file["name"] + ".blend1"))
else : #If the max backup amount has been reached, then check for the oldest file and overwrite that one.
if file["backup_amount"] <= len(currentFiles) :
replaceFile = {"modified_date":None, \
"fullname":""}
for f in currentFiles :
stats = os.stat(os.path.join(file["directory"], file["backup_directory"], f)) #Get attributes from a file.
if replaceFile["fullname"] == "" : #This will happen only the first time.
replaceFile["fullname"] = f
replaceFile["modified_date"] = time.asctime(time.localtime(stats[ST_MTIME]))
else : # Is the previous file older or newer? If it's older, then you'd want to overwrite that one instead. Go through all backup-files.
temp_modified = time.asctime(time.localtime(stats[ST_MTIME]))
if replaceFile["modified_date"] > temp_modified :
replaceFile["fullname"] = f
replaceFile["modified_date"] = temp_modified

#When the loop is finished, the oldest file has been found, and will be overwritten.
shutil.move(file["fullpath"] + "1", os.path.join(file["directory"], file["backup_directory"], replaceFile["fullname"]))
else : #If the max backup amount hasn't been reached, and the folder isn't empty.
#Then check for the next number, and then just move the file over with the correct number.
replaceFile = "" #Location.
for f in currentFiles :
for c in range(1, int(file["backup_amount"]) + 1) :
if not os.path.isfile(os.path.join(file["directory"], file["backup_directory"], file["name"] + file["extension"] + str(c))) :
shutil.move(file["fullpath"] + "1", os.path.join(file["directory"], file["backup_directory"], file["name"] + file["extension"] + str(c)))
replaceFile = f
break
if replaceFile != "" : #File to replace has been found, break out.
break