To fix this manually, rename .qgz to .zip, extract zip, change paths, re-zip, rename .zip to .qgz.
Alternatively, I've hacked together a very basic and very minimally tested python script to do this (Python 3 only unless you modify it):
from fnmatch import filter
from io import BytesIO
from os import (walk, path, rename)
from zipfile import ZipFile, ZIP_DEFLATED
def main(in_dir, old_path, new_path, backup_suffix=None):
for (dirpath, dirnames, filenames) in walk(in_dir):
qgzs = filter(filenames, '*.qgz')
for qgz in qgzs:
qgz_path = path.join(dirpath, qgz)
mem_qgz = BytesIO()
with ZipFile(qgz_path, 'r') as in_qgz, ZipFile(mem_qgz, 'w', compression=ZIP_DEFLATED) as tmp_qgz:
for f in in_qgz.infolist():
data = in_qgz.read(f.filename).decode('UTF-8')
if f.filename.endswith('.qgs'):
data = data.replace('source="{}'.format(old_path), 'source="{}'.format(new_path))
tmp_qgz.writestr(f.filename, data)
if backup_suffix is not None:
backup_suffix = backup_suffix if backup_suffix.startswith('.') else '.' + backup_suffix
try:
rename(qgz_path, qgz_path + backup_suffix)
except FileExistsError as err:
print('Unable to backup file, skipping {} ({})'.format(qgz_path, err))
continue
with open(qgz_path, 'wb') as out_qgz:
out_qgz.write(mem_qgz.getvalue())
if __name__ == '__main__':
backup_suffix = '.orig' # Don't overwrite orig .qgz (just in case...), append ".orig"
in_dir = r'D:\Temp'
old_path = 'D:\\' # 2 trailing backslashes on Windows, 1 forward for Unix like paths
new_path = r'C:\\'
main(in_dir, old_path, new_path, backup_suffix)
Note: the path changes are a kludge and rely on a simple search and replace, but the zipped .qgs file is actually XML and really should be parsed as such.
os.walk
(os.path.walk
in python 2x) andzipfile
.