diff --git a/mythtv/programs/scripts/python_pathfix.py b/mythtv/programs/scripts/python_pathfix.py
new file mode 100755
index 0000000000..9533c5b6fc
--- /dev/null
+++ b/mythtv/programs/scripts/python_pathfix.py
@@ -0,0 +1,218 @@
+#
+# python_pathfix - adjust python shebang paths
+#
+
+from __future__ import print_function
+from __future__ import unicode_literals
+import sys
+import os
+from stat import ST_MODE
+import getopt
+
+def main():
+
+    # Pick up default interpreter (ours)
+    python_interpreter = os.path.normcase(sys.executable).encode()
+
+    # Don't bother reporting
+    verbose = False
+
+    # Set default return code
+    ret = 0
+
+    usage = ('usage: %s -v -i /python_interpreter file-or-directory ...\n' % sys.argv[0])
+
+    try:
+        opts, args = getopt.getopt(sys.argv[1:], 'i:v')
+    except getopt.GetoptError as msg:
+        sys.stderr.write(str(msg) + '\n')
+        sys.stderr.write(usage)
+        sys.exit(1)
+    for o, a in opts:
+        if o == '-i':
+            python_interpreter = a.encode()
+        if o == '-v':
+            verbose = True
+
+    if not python_interpreter or not python_interpreter.startswith(b'/'):
+        sys.stderr.write('-i interpreter option invalid (must be specified as a full path)\n')
+        sys.stderr.write(usage)
+        sys.exit(1)
+
+    if not args:
+        sys.stderr.write('file or directories not specified\n')
+        sys.stderr.write(usage)
+        sys.exit(1)
+
+    for arg in args:
+        if os.path.islink(arg):
+            continue
+        if os.path.isfile(arg):
+            if pathfix(filename=arg,
+                       verbose=verbose,
+                       python_interpreter=python_interpreter):
+                ret = 1
+        if os.path.isdir(arg):
+            for root, subdirs, files in os.walk(arg):
+                for f in files:
+                    filename = os.path.join(root, f)
+                    if os.path.islink(filename):
+                        continue
+                    if os.path.isfile(filename):
+                        if pathfix(filename=filename,
+                                   verbose=verbose,
+                                   python_interpreter=python_interpreter):
+                            ret = 1
+
+    sys.exit(ret)
+
+def pathfix(filename=None, verbose=False, python_interpreter='/usr/bin/python'):
+    if not filename:
+        if verbose:
+            sys.stdout.write('filename not provided\n')
+        return 1
+    # open input file
+    try:
+        infile = open(filename, 'rb')
+    except IOError as msg:
+        sys.stderr.write('%s: open failed: %r\n' % (filename, msg))
+        return 1
+    # process first line
+    try:
+        firstline = infile.readline()
+    except IOError as msg:
+        sys.stderr.write('%s: read failed: %r\n' % (filename, msg))
+        try:
+            infile.close()
+        except IOError as msg:
+            sys.stderr.write('%s: close failed: %r\n' % (filename, msg))
+        return 1
+    if firstline.rstrip(b'\n').find(b' -') != -1:
+        existingargs = firstline.rstrip(b'\n')[firstline.rstrip(b'\n').find(b' -'):]
+    else:
+        existingargs = b''
+    newline = b'#!' + python_interpreter + existingargs + b'\n'
+    if (not firstline.startswith(b'#!')) or (b"python" not in firstline) or (firstline == newline):
+        if verbose:
+            sys.stdout.write('%s: unchanged\n' % (filename))
+        try:
+            infile.close()
+        except IOError as msg:
+            sys.stderr.write('%s: close failed: %r\n' % (filename, msg))
+        return 0
+    # create temporary output
+    head, tail = os.path.split(filename)
+    tempname = os.path.join(head, '@' + tail)
+    try:
+        outfile = open(tempname, 'wb')
+    except IOError as msg:
+        sys.stderr.write('%s: create failed: %r\n' % (tempname, msg))
+        try:
+            infile.close()
+        except IOError as msg:
+            sys.stderr.write('%s: close failed: %r\n' % (filename, msg))
+        return 1
+    if verbose:
+        sys.stdout.write('%s: updating\n' % (filename))
+    # write first new line to temporary output
+    try:
+        outfile.write(newline)
+    except IOError as msg:
+        sys.stderr.write('%s: write failed: %r\n' % (tempname, msg))
+        try:
+            infile.close()
+        except IOError as msg:
+            sys.stderr.write('%s: close failed: %r\n' % (filename, msg))
+        try:
+            outfile.close()
+        except IOError as msg:
+            sys.stderr.write('%s: close failed: %r\n' % (tempname, msg))
+        return 1
+    # copy rest of file
+    while True:
+        try:
+            chunk = infile.read(32678)
+        except IOError as msg:
+            sys.stderr.write('%s: read failed: %r\n' % (filename, msg))
+            try:
+                infile.close()
+            except IOError as msg:
+                sys.stderr.write('%s: close failed: %r\n' % (filename, msg))
+            try:
+                outfile.close()
+            except IOError as msg:
+                sys.stderr.write('%s: close failed: %r\n' % (tempname, msg))
+            try:
+                os.remove(tempname)
+            except OSError as msg:
+                sys.stderr.write('%s: remove failed: %r\n' % (tempname, msg))
+            return 1
+        if not chunk:
+            break
+        try:
+            outfile.write(chunk)
+        except IOError as msg:
+            sys.stderr.write('%s: write failed: %r\n' % (tempname, msg))
+            try:
+                infile.close()
+            except IOError as msg:
+                sys.stderr.write('%s: close failed: %r\n' % (filename, msg))
+            try:
+                outfile.close()
+            except IOError as msg:
+                sys.stderr.write('%s: close failed: %r\n' % (tempname, msg))
+            try:
+                os.remove(tempname)
+            except OSError as msg:
+                sys.stderr.write('%s: remove failed: %r\n' % (tempname, msg))
+            return 1
+    # close files
+    try:
+        infile.close()
+    except IOError as msg:
+        sys.stderr.write('%s: close failed: %r\n' % (filename, msg))
+        try:
+            outfile.close()
+        except IOError as msg:
+            sys.stderr.write('%s: close failed: %r\n' % (tempname, msg))
+        try:
+            os.remove(tempname)
+        except OSError as msg:
+            sys.stderr.write('%s: remove failed: %r\n' % (tempname, msg))
+        return 1
+    try:
+        outfile.close()
+    except IOError as msg:
+        sys.stderr.write('%s: close failed: %r\n' % (tempname, msg))
+        try:
+            os.remove(tempname)
+        except OSError as msg:
+            sys.stderr.write('%s: remove failed: %r\n' % (tempname, msg))
+        return 1
+    # copy the file's mode to the temp file
+    try:
+        statbuf = os.stat(filename)
+        os.chmod(tempname, statbuf[ST_MODE] & 0o7777)
+    except OSError as msg:
+        sys.stderr.write('%s: warning, chmod failed: %r\n' % (tempname, msg))
+    # Remove original file
+    try:
+        os.remove(filename)
+    except OSError as msg:
+        sys.stderr.write('%s: remove failed: %r\n' % (filename, msg))
+        try:
+            os.remove(tempname)
+        except OSError as msg:
+            sys.stderr.write('%s: remove failed: %r\n' % (tempname, msg))
+        return 1
+    # move the temp file to the original file
+    try:
+        os.rename(tempname, filename)
+    except OSError as msg:
+        sys.stderr.write('%s: rename failed: %r\n' % (filename, msg))
+        # leave the tempname alone (might be used for recovery)
+        return 1
+    return 0
+
+if __name__ == '__main__':
+    main()
diff --git a/mythtv/programs/scripts/scripts.pro b/mythtv/programs/scripts/scripts.pro
index 3676d8b997..5656edeeb9 100644
--- a/mythtv/programs/scripts/scripts.pro
+++ b/mythtv/programs/scripts/scripts.pro
@@ -2,10 +2,133 @@ include ( ../../settings.pro )
 
 TEMPLATE = aux
 
-installscripts.path = $${PREFIX}/share/mythtv
-installscripts.files = database/*
+#
+# database backup/restore scripts are standalone
+#
+database_scripts.path = $${PREFIX}/share/mythtv
+database_scripts.files = database/*
+INSTALLS += database_scripts
 
-installinternetscripts.path = $${PREFIX}/share/mythtv
-installinternetscripts.files = internetcontent metadata hardwareprofile
+#
+# We leverage the capability of qmake to invoke an extra
+# "compiler" to transform the python scripts and adjust
+# python script shebangs.  Since the scripts depend on
+# the python bindings, and when using_python_bindings is
+# true we know we have the bindings and a usable python
+# executable (verified as part of configure), we can use
+# a python script to modify the shebang on scripts in the
+# same way that the bindings setup.py will modify the
+# shebangs for executable scripts (typically something of
+# the form #!/usr/bin/pythonX).
+#
+# However, there is an exception for the Music metadata
+# scripts, which do not require the python bindings.  We
+# try another way to locate a python executable to be
+# used to modify the shebangs that may be less accurate.
+# It is expected that typically one will build the
+# python bindings, making thise case less likely in
+# practice.
+#
 
-INSTALLS += installscripts installinternetscripts
+using_bindings_python {
+
+    PYTHON_SOURCES += hardwareprofile/*
+    PYTHON_SOURCES += internetcontent/*.py internetcontent/nv_python_libs
+    PYTHON_SOURCES += metadata/*
+
+    python_pathfix.output  = $${OBJECTS_DIR}/${QMAKE_FILE_NAME}
+    python_pathfix.commands = $${QMAKE_COPY_DIR} ${QMAKE_FILE_NAME} $${OBJECTS_DIR}/${QMAKE_FILE_NAME} $$escape_expand(\n\t) \
+                              $${PYTHON} ./python_pathfix.py $${OBJECTS_DIR}/${QMAKE_FILE_NAME}
+    python_pathfix.input = PYTHON_SOURCES
+    python_pathfix.variable_out = PYTHON_FIXUPS
+    python_pathfix.CONFIG += no_link target_predeps
+    QMAKE_EXTRA_COMPILERS += python_pathfix
+
+    hardwareprofile_scripts.path = $${PREFIX}/share/mythtv/
+    hardwareprofile_scripts.files = $${OBJECTS_DIR}/hardwareprofile
+    hardwareprofile_scripts.CONFIG += no_check_exist
+
+    metadata_scripts.path = $${PREFIX}/share/mythtv/
+    metadata_scripts.files = $${OBJECTS_DIR}/metadata
+    metadata_scripts.CONFIG += no_check_exists
+
+    internetcontent_scripts.path = $${PREFIX}/share/mythtv/
+    internetcontent_scripts.files = $${OBJECTS_DIR}/internetcontent
+    internetcontent_scripts.CONFIG += no_check_exists
+
+    INSTALLS += hardwareprofile_scripts metadata_scripts internetcontent_scripts
+
+    unix|macx|mingw:QMAKE_CLEAN += -r $${OBJECTS_DIR}/hardwareprofile/distros \
+                                      $${OBJECTS_DIR}/internetcontent/nv_python_libs \
+                                      $${OBJECTS_DIR}/metadata/Movie \
+                                      $${OBJECTS_DIR}/metadata/Music \
+                                      $${OBJECTS_DIR}/metadata/Television
+    unix|macx|mingw:QMAKE_DISTCLEAN += -r $${OBJECTS_DIR}/hardwareprofile \
+                                          $${OBJECTS_DIR}/internetcontent \
+                                          $${OBJECTS_DIR}/metadata
+    win32-msvc*:QMAKE_CLEAN += /s /f /q $${OBJECTS_DIR}/hardwareprofile/distros \
+                                        $${OBJECTS_DIR}/internetcontent/nv_python_libs \
+                                        $${OBJECTS_DIR}/metadata/Movie \
+                                        $${OBJECTS_DIR}/metadata/Music \
+                                        $${OBJECTS_DIR}/metadata/Television $$escape_expand(\n\t) \
+                               rd /s /q $${OBJECTS_DIR}/hardwareprofile/distros \
+                                        $${OBJECTS_DIR}/internetcontent/nv_python_libs \
+                                        $${OBJECTS_DIR}/metadata/Movie \
+                                        $${OBJECTS_DIR}/metadata/Music \
+                                        $${OBJECTS_DIR}/metadata/Television
+    win32-msvc*:QMAKE_DISTCLEAN += /s /f /q $${OBJECTS_DIR}/*.* $$escape_expand(\n\t) \
+                                   rd /s /q $${OBJECTS_DIR}/hardwareprofile \
+                                            $${OBJECTS_DIR}/internetcontent \
+                                            $${OBJECTS_DIR}/metadata
+
+} else {
+
+    # Try to verify our python exists
+    win32 {
+        PYTHON_BIN = $$system(where $${PYTHON})
+    }
+    unix|macx|mingw {
+        PYTHON_BIN = $$system(which $${PYTHON})
+    }
+
+    PYTHON_SOURCES += metadata/Music/*
+
+    python_pathfix.output  = $${OBJECTS_DIR}/${QMAKE_FILE_NAME}
+    python_pathfix.commands = $${QMAKE_COPY_DIR} ${QMAKE_FILE_NAME} $${OBJECTS_DIR}/${QMAKE_FILE_NAME}
+    !isEmpty(PYTHON_BIN) {
+        python_pathfix.commands += $$escape_expand(\n\t)
+        python_pathfix.commands += $${PYTHON} ./python_pathfix.py $${OBJECTS_DIR}/${QMAKE_FILE_NAME}
+    }
+    python_pathfix.input = PYTHON_SOURCES
+    python_pathfix.variable_out = PYTHON_FIXUPS
+    python_pathfix.CONFIG += no_link target_predeps
+    QMAKE_EXTRA_COMPILERS += python_pathfix
+
+    internetcontent_python_scripts.path = $${PREFIX}/share/mythtv/
+    internetcontent_python_scripts.files = $${OBJECTS_DIR}/metadata
+    internetcontent_python_scripts.CONFIG += no_check_exist
+
+    INSTALLS += internetcontent_python_scripts
+
+    unix|macx|mingw:QMAKE_CLEAN += -r $${OBJECTS_DIR}/metadata/Music/*
+    unix|macx|mingw:QMAKE_DISTCLEAN += -r $${OBJECTS_DIR}/metadata
+    win32-msvc*:QMAKE_CLEAN += /s /f /q $${OBJECTS_DIR}/metadata/Music/*.* $$escape_expand(\n\t) \
+                               rd /s /q $${OBJECTS_DIR}/metadata/Music/*.*
+    win32-msvc*:QMAKE_DISTCLEAN += /s /f /q $${OBJECTS_DIR}/metadata/*.* $$escape_expand(\n\t) \
+                                   rd /s /q $${OBJECTS_DIR}/metadata
+
+
+}
+
+#
+# internetcontent perl scripts do not require transformation
+# but do require the perl bindings to function
+#
+using_bindings_perl {
+
+    internetcontent_perl_scripts.path = $${PREFIX}/share/mythtv/internetcontent
+    internetcontent_perl_scripts.files += internetcontent/nv_perl_libs internetcontent/*.pl
+
+    INSTALLS += internetcontent_perl_scripts
+
+}
