How to open the latest file automatically when launching software from a Task

This question was asked over in the #shotguncreate room, and I thought I was worth sharing here too.

When launching software like Nuke from a Task either in Shotgun Create or via the browser integration, you may want it to open the latest file automatically.

Below is an example of some code that can be used to open the latest file automatically. However, it is not really production-ready code and makes some assumptions.

For example, it’s not always easy to know what the latest file is. You could have two or more files with different names but the same version number! The example below would simply pick the last found.
However, if your workflow allows you to make assumptions about what the latest file is then you should be able to implement something like the following:

Example code:

You need to take over the hook of the tk-multi-launchapp .

Then replace the script contents with the following:

import os
import re
import sys
import tank
import sgtk

class AppLaunch(tank.Hook):

    def execute(self, app_path, app_args, version, engine_name, **kwargs):

        engine = sgtk.platform.current_engine()

        if engine_name == "tk-nuke" and engine.context.task is not None:
            self.logger.debug("Finding latest file to load on startup ...")

            # Get the settings for the workfiles app in the environment we will be launching Nuke in.
            # This is so we can find out the publish and work templates it would use.
            app_settings = sgtk.platform.find_app_settings(engine_name,

            # extracting the templates from the app settings
            publish_template = app_settings[0]['settings']['template_publish']
            work_template = app_settings[0]['settings']['template_work']

            # Now get the latest work and publish file along with the version number for each
            work_file, work_file_version = self.get_next_version(engine.sgtk, engine.context, publish_template)
            publish_file, publish_file_version = self.get_next_version(engine.sgtk, engine.context, work_template)

            # Figure out which of the latest publish and work file is the highest version and use that.
            # In the situation where both are the same, use the work file
            file_to_open = work_file if work_file_version >= publish_file_version else publish_file
            # Now add the file path to the Nuke launch args. If you were doing this for software other than Nuke
            # Then you will need to handle it in the way in which that software expects the arg to be passed.
            app_args = "{0} {1}".format(file_to_open, app_args)

        system = sys.platform

        if system == "linux2":
            # on linux, we just run the executable directly
            cmd = "%s %s &" % (app_path, app_args)

        elif system == "darwin":
            # If we're on OS X, then we have two possibilities: we can be asked
            # to launch an application bundle using the "open" command, or we
            # might have been given an executable that we need to treat like
            # any other Unix-style command. The best way we have to know whether
            # we're in one situation or the other is to check the app path we're
            # being asked to launch; if it's a .app, we use the "open" command,
            # and if it's not then we treat it like a typical, Unix executable.
            if app_path.endswith(".app"):
                # The -n flag tells the OS to launch a new instance even if one is
                # already running. The -a flag specifies that the path is an
                # application and supports both the app bundle form or the full
                # executable form.
                cmd = "open -n -a \"%s\"" % (app_path)
                if app_args:
                    cmd += " --args %s" % app_args
                cmd = "%s %s &" % (app_path, app_args)

        elif system == "win32":
            # on windows, we run the start command in order to avoid
            # any command shells popping up as part of the application launch.
            cmd = "start /B \"App\" \"%s\" %s" % (app_path, app_args)

        # run the command to launch the app
        exit_code = os.system(cmd)

        return {
            "command": cmd,
            "return_code": exit_code

    def get_next_version(self, tk, context, template_name, ):
        Get the highest version file found on disk for a given template
        :param tk:
        :param template_name:
        template = tk.templates[template_name]
        fields = context.as_template_fields(template)

        # Get a list of existing file paths on disk that match the template and provided fields
        # Skip the version field as we want to find all versions, not a specific version.
        skip_fields = ["version"]
        file_paths = tk.paths_from_template(
        # now loop over the files and find the highest version file
        latest_file = None
        highest_version = 0
        for a_file in file_paths:
            # extract the values from the path so we can read the version.
            path_fields = template.get_fields(a_file)
            if path_fields["version"] > highest_version:
                highest_version = path_fields["version"]
                latest_file = a_file
        return latest_file, highest_version

Also, if the latest file is a PublishedFile, then really it should be copied to the working directory so that it can be worked on. This guide may be helpful with trying to add that behaviour.

The original topic is here: