I want to write a Nautilus script in Python. Is that possible? If it is possible, how can I do that?
2 Answers
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.
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.

- 105,154
- 20
- 279
- 497

- 37,204
-
2Note that while the question and answer are specific to Python (and it does work), the same strategy is equally effective for Bash, Perl, Ruby, and other scripting languages so long as the #! points to the right interpreter. – Freedom_Ben Aug 30 '13 at 16:52
-
@Freedom_Ben Actually, it's not just the scripting languages that can be used, but also compiled executable. Nautilus simply executes whatever file is in that folder, and provides files on which user wants to operate to the executable via environment. – Sergiy Kolodyazhnyy Feb 20 '17 at 00:11
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
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("extension initialized")
# Hmm. This gets constantly called.
def get_file_items(self, entries):
d("---\nInspect selected entries")
if len(entries) < 1:
d("nothing selected")
return []
item = Nautilus.MenuItem(
name="MyInspectExtension::inspect_selected_entries",
label="Inspect selected entries",
tip=f"Write infos about the `entries` parameter to {logpath}",
)
item.connect("activate", inspect, entries)
return [item]
# Dito.
def get_background_items(self, folder):
logging.debug("---\nInspect current folder")
item = Nautilus.MenuItem(
name="MyInspectExtension::inspect_current_folder",
label="Inspect current folder",
tip=f"write infos about the `folder` parameter to {logpath}",
)
item.connect("activate", 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.

- 131
- 6