17

I want to write a Nautilus script in Python. Is that possible? If it is possible, how can I do that?

htorque
  • 66,086

2 Answers2

21

Nautilus Scripts

Nautilus scripts can be written in any programming language, including python. You just need to make your python source file executable and copy it to ~/.gnome2/nautilus-scripts in Ubuntu versions prior to 14.04. For Ubuntu 14.04 and newer the directory is different: ~/.local/share/nautilus/scripts

You will also need to add #!/usr/bin/env python as the first line of the file. Note that by default #!/usr/bin/env python points to Python2. If you need Python 3 specifically, use #!/usr/bin/env python3.

Once you have done all this, the script will be accessible from the scripts sub-menu of the right click menu in Nautilus.

nautilus scripts menu

See also:https://help.ubuntu.com/community/NautilusScriptsHowto

Nautilus Extensions

Nautilus extensions have more flexibility than scripts - eg. they can be used to add an item directly to the context menu. There is are python bindings available (python-nautilus).

Visit the web page of this library and view the documentation for more information.

dv3500ea
  • 37,734
0

Here is a script template and an extension template.

To restart Nautilus and reload your code, execute nautilus -q && nautilus ~.

Scripts

This will log the environment variables which Nautilus sets for scripts to ~/script.log. It will also log raisable errors (no syntax errors).

myscript.py

#!/usr/bin/python3

import os, logging

logpath = os.path.expanduser('~/script.log')

logging.basicConfig( filename=logpath, encoding='utf-8', level=logging.DEBUG, format='%(message)s', )

def logenv(env): logging.debug(os.environ[env].strip())

try: logenv('NAUTILUS_SCRIPT_SELECTED_FILE_PATHS') logenv('NAUTILUS_SCRIPT_SELECTED_URIS') logenv('NAUTILUS_SCRIPT_CURRENT_URI') #~ logenv('NAUTILUS_SCRIPT_WINDOW_GEOMETRY') # seems to be not supported any more. except: from traceback import format_exc as exception_as_string logging.debug(exception_as_string())

Put the script into ~/.local/share/nautilus/scripts. Make it executable. Restart Nautilus (see above). Select some files or folders in Nautilus and right click. The script appears under the "Scripts" menu entry.

Extensions

Extensions are a little bit more complex, but one can do more with them, e.g. chained menus are possible.

First install nautilus-python using your package manager.

  • Fedora: sudo dnf install nautilus-python <- can confirm, works
  • Debian: sudo apt install nautilus-python
  • Arch: sudo pacman -Sy python-nautilus

Source

Every extension needs to create a class which extends GObject.GObject and Nautilus.MenuProvider.

myextension.py

#!/usr/bin/python3

import os, logging

logpath = '~/extension.log'

logging.basicConfig( filename=os.path.expanduser(logpath), encoding='utf-8', level=logging.DEBUG, format='%(message)s', )

d = logging.debug

try:

from gi.repository import Nautilus, GObject

class MyInspectExtension(GObject.GObject, Nautilus.MenuProvider):

    def __init__(self):
        super().__init__()
        d(&quot;extension initialized&quot;)

    # Hmm. This gets constantly called.
    def get_file_items(self, entries):
        d(&quot;---\nInspect selected entries&quot;)
        if len(entries) &lt; 1:
            d(&quot;nothing selected&quot;)
            return []
        item = Nautilus.MenuItem(
            name=&quot;MyInspectExtension::inspect_selected_entries&quot;,
            label=&quot;Inspect selected entries&quot;,
            tip=f&quot;Write infos about the `entries` parameter to {logpath}&quot;,
        )
        item.connect(&quot;activate&quot;, inspect, entries)
        return [item]

    # Dito.
    def get_background_items(self, folder):
        logging.debug(&quot;---\nInspect current folder&quot;)
        item = Nautilus.MenuItem(
            name=&quot;MyInspectExtension::inspect_current_folder&quot;,
            label=&quot;Inspect current folder&quot;,
            tip=f&quot;write infos about the `folder` parameter to {logpath}&quot;,
        )
        item.connect(&quot;activate&quot;, inspect, [folder])
        return [item]

def inspect(menu, entries):
    for thing in entries:
        d('---')
        for attrname in dir(thing):
            if attrname.startswith('get_') or attrname.startswith('is_'):
                attr = getattr(thing, attrname)
                try:
                    if callable(attr):
                        d(f'{attrname}(): {attr()}')
                    else:
                        d(f'{attrname}: {attr}')
                except:
                    pass

except: from traceback import format_exc d(format_exc())

Put the extension script into ~/.local/share/nautilus-python/extensions. (Notice, nautilus-python, not nautilus). Make it executable. Restart Nautilus (see above).

Then, when you right-click on selected files/folders, MyInspectExtension.get_file_items is called, when you right-click on the background, MyInspectExtension.get_background_items is called. Both install their menu entry, and, in this case, forward to inspect.

More extension examples can be found in the nautilus-python repo.

Nautilus seems to constantly reload extensions, every second or so. You can see this in the log, when a Nautilus instance is open. I don't know why that is so, but it may indicate that one may not install too many and too heavy extensions.