I now have a Python script which
a) looks through all the files in the dvr/log directory looking for ones which contain the recording path, which for me is /var/media/DATA/Recordings.
b) use a regex to pull out the rest of the pathname, and construct the full pathname of the file.
c) construct the full pathname of the destination of the move, which is a NAS mounted on /storage/recordings.
d) ensure that the full path to the destination file exists on the NAS (I have TVHeadend set to create subdirectories per program name).
e) copy source to destination.
f) if OK, overwrite the database file with one which has the path updated to point to the NAS.
g) if OK, unlink the source file.
However, as soon as I overwrite the database file, the recordings vanish from the Completed Recordings tab and appear in Failed Recordings with a reason of File Missing. I checked that the path in the database file matched the true location.
If I kill the TVHeadend process and allow OpenELEC to restart it, then refresh the web page, the recordings now appear in Finished Recordings rather than Failed Recordings.
I had planned to run the Python script via cron at 03:00 so I guess I will invoke it from a shell script then when finished kill TVHeadend with "killall".