blender file version

when you open an old file in 2.74 or latest build
is there a way to tell under what bl version it was saved !

like if old file was saved under 2.49
is there a script to identify this 2.49 ?

happy bl

>>> bpy.data.version # file version
(2, 72, 2)

>>> bpy.app.version # program version
(2, 73, 0)

can you elaborate a little

what is the difference between the 2 lines ?

and this seems to give the running file version not the file being opened up !

or a way to list file’s version in a folder may be!

like I need to know the creation bl version for each file
not the running bl

thanks
happy bkl

I did comment them… one is the version the blend file was saved in, the other the version of Blender that you are currently running.

You could also read the first bytes of the blend file and interpret them manually:

import bpy
import struct
import os.path

filepath = bpy.data.filepath
try:
    file = open(filepath, "rb")
    file.seek(7)
    bitness, endianess, major, minor = struct.unpack("sss2s", file.read(5))
    print("v{}.{}".format(major.decode(), minor.decode()))
    print("64 bit" if bitness == b"-" else "32 bit")
    print("little-endian" if endianess == b"v" else "big-endian")
except IOError:
    print("Can't read file '{}'".format(filepath))
except Exception as err:
    print(err)

http://archive.blender.org/development/architecture/blender-file-format/index.html

Not sure how Blender knows the patch version (Z in X.Y.Z) though for files…

what does the # file version means ?

If I run
bpy.data.version

I get the running bl version !
and not the version from the file being opened up !

will try the other script

thanks
happy bl

did test with last snippet
and replace RB name with file name
file = open( filepath , “z1.blend”)

get error on

err = invalid mode: ‘z1.blend’

not certain what this should do !

by the way in post #4 code
at first I had a Unicode mistake somehow!

thanks
happy bl

bpy.app.version shows the version that was used to save the blend. If you save an old file in a new Blender, the version number will change. If you haven’t saved your current creation, the version number of the home file (startup.blend) will be used instead. Note that a reload is required after saving a blend, or you will get a wrong number.

‘rb’ is not a filename, it’s the mode to open the file in (r=read, b=binary).

corrected file


import bpy
import struct
import os.path

filepath = bpy.data.filepath
	
#	'rb' is not a filename, it's the mode to open the file in (r=read, b=binary). 
	
try:
	file = open( filepath , "rb")
#	file = open( filepath , "z1")
	file.seek(7) 
	bitness ,  endianess, major, minor = struct.unpack("sss2s", file.read(5))    
	print("v{}.{}".format(major.decode(), minor.decode()))
	print("64 bit" if bitness == b"-" else "32 bit")
	print("little-endian" if endianess == b"v" else "big-endian")
	
except IOError:
	print (" can't read file  '{}'".format(filepath) )
	
except Exception as err:
	print ('err =', err)
	
	


but get this error

err = ‘utf-8’ codec can’t decode bytes in position 0-1: unexpected end of data

thanks
happy bl

post me this:

import bpy
import struct
import os.path

filepath = bpy.data.filepath
try:
    file = open(filepath, "rb")
    print(file.read(12))
except IOError:
    print("Can't read file '{}'".format(filepath))
except Exception as err:
    print(err)

it gives the following

b’\x1f\x8b\x08\x00\x00\x00\x00\x00\x04\x0b\xec\x9d’

no idea what it is !
see a 9 at the end !

what is it supposed to do ?
like read all files in same folder then the file with script
and gives their version

happy bl

It opens the file at “filepath” and reads the first 12 bytes. Your file is not a blend file, otherwise it would go like this:

b"BLENDER-v274"

If you supply the filepath to a blend, my script will read the header and determine the version. You could do this with a hex editor too of course, since it’s pretty literal.

I created a new folder with only one blend file with the script in text editor and ran it

and still get code like this

read 12 = b’\x1f\x8b\x08\x00\x00\x00\x00\x00\x04\x0b\xec\xbd’

anything else missing ?

any special requirement for the filepath name ?

it is a bit long with many sub folder

thanks
happy bl

oh, might the blend be stored as compressed blend? Then it would require unpacking (at least partially) before the header can be read I guess.

yup it is !
anyway to get it from compress file

I mean most file now are compress to save space and time !

and is there a way like reading all files in same folder and get the bl version

I have like 1000 old files that I cannot really know bl version
and can be useful for bug tracker too!

thanks
happy bl

Compression saves storage space, but time only in terms of transfer duration. The time necessary to compress and decompress data can be significant (depends on compression algorithm and level).

Added gzip support:

import bpy
import struct
import os.path

filepath = bpy.data.filepath
is_compressed = False

try:
    file = open(filepath, "rb")
    header = file.read(12)
    if header[:2] == b"\x1f\x8b":
        file.close()
        import gzip
        file = gzip.GzipFile(filepath, "rb")
        header = file.read(12)
        is_compressed = True
        
    if header[:7] != b"BLENDER":
        raise Exception("Not a .blend-file!")
        
    bitness, endianess, major, minor = struct.unpack("sss2s", header[7:])
    print("v{}.{}".format(major.decode(), minor.decode()))
    print("64 bit" if bitness == b"-" else "32 bit")
    print("little-endian" if endianess == b"v" else "big-endian")
    print("compressed" if is_compressed else "uncompressed")
    
except IOError:
    print("Can't read file '{}'".format(filepath))
except Exception as err:
    print(err)

did a test on an old file

v2.48
32 bit
little-endian
uncompressed

now is it possible to run this from a file and read all the files in same folder and get list
of files name and bl version in console

that way it is faster and gives the version for all files

wondering why this was not added in console when you open a file
very useful for bug tracker and have an idea of the bl of read file!

thanks

Sure you could do that

import bpy
import struct
import os.path
import gzip
from glob import glob

# Scan my desktop for blends
dirpath = r"C:\Users\CoDEmanX\Desktop\*.blend"

for filepath in glob(dirpath):
    is_compressed = False
    try:
        file = open(filepath, "rb")
        header = file.read(12)
        if header[:2] == b"\x1f\x8b":
            file.close()
            file = gzip.GzipFile(filepath, "rb")
            header = file.read(12)
            is_compressed = True
            
        if header[:7] != b"BLENDER":
            continue
            
        bitness, endianess, major, minor = struct.unpack("sss2s", header[7:])
        
        print("{file}: v{major}.{minor} ({bitness} {endianess}{compression})".format(
            file=os.path.basename(filepath),
            major=major.decode(),
            minor=minor.decode(),
            bitness="64bit" if bitness == b"-" else "32bit",
            endianess="LE" if endianess == b"v" else "BE",
            compression=" Gzip" if is_compressed else ""
        ))
        
    except Exception:
        continue

Can’t see how this would be helpful for bug reporting however, because you would upload a single sample blend most of the time and the developers need to know the exact version of Blender, not the blend file.

is it possible from file’s name
to extract the path alone and then the filename

if possible would like to print the path for folders at top ounce
then after make list with only the blend file name and version

and also add list to text editor file to save it there
I got example for that but need the file name only

I replace the path at beginning with

curfolder = os.getcwd()
curfolder = curfolder + “*.blend”
print (‘curfolder =’, curfolder )
print ()

and seems to work fine

thanks

os.path.join(os.path.dirname(filepath), “*.blend”)