17

In a program which I am writing I want to offer the functionality to open the directory where the file which I am currently processing is located and automatically select that file (so that the user does not need to search for it).

I know that I can open a directory in the default file manager using

xdg-open /path/to/directory

I know that I can open a directory in nautilus and select a file using

nautilus /path/to/file.txt

I thought that I could use

xdg-mime query default inode/directory

to get the default file manager and - if it is nautilus - call it as shown above. But, despite the fact that nautilus is the default on my system (xdg-open opens nautilus and so does the places menu in the gnome shell), xdg-mime returns Thunar.desktop. (I have tried find / -name Thunar.desktop -mount 2>/dev/null but it did not find anything.)

Also, I do not know how to open a directory and select a subdirectory in nautilus (with the above mentioned approach it would open the subdirectory).

How can I open a directory in the default filemanager and select a file in that directory (if selecting a directory, too, was possible that would be great, but for this application not needed) or at least find out the default filemanager so that I can call it directly?

5 Answers 5

16

1. To open a directory and select a subdirectory/file in nautilus:

nautilus --select path/to/file/or/directory

From nautilus(1) man page:

-s, --select
  Select specified URI in parent folder.

2. xdg-mime returns Thunar.desktop but xdg-open opens nautilus

xdg-mime uses mimeapps.list to determine the default application to use.

Separate mimeapps.list files exist to handle user-specific, system-specific and distribution-specific requirements. Their lookup order can be found over here.

mimeapps.list lists default applications for a given mimetype under [Default Applications] section. It allows to list multiple default applications in their decreasing order of preference. For example :

[Default Applications]
mimetype1 = default1.desktop;default2.desktop;

where mimetype1 is the mime type and *.desktop are the desktop files.

xdg-open searches for desktop file down the lookup order, across the preference list till it finds a valid desktop file. If no such file is found across all the files then the most preferred one according to the associations is chosen and is used as default application.

So in case of our example, let us suppose default1.desktop is not present on our system, so xdg-open will try to open our file using default2.desktop. However, xdg-mime returns default1.desktop which is the first entry in our mimeapps.list file.

In your case default1.desktop must be Thunar.desktop hence the output. However it is not installed on your system. So xdg-open opens your file/directories using nautilus which is present on your system. To verify this, you can check your mimeapps.list file for line containing inode/directory. For Ubuntu 17.10, the location of mimeapps.list file is : /usr/share/applications/defaults.list

NOTE: The complete algorithm to determine 'Default Applications' can be found here.

7
  • In case something has remained unanswered or if there is any confusion, drop a comment.
    – Amit Singh
    Commented Dec 14, 2017 at 7:16
  • 1
    Your excellent answer looked like a question on the first spot (what is a delete reason), it could mislead reviewers, so I edited it a little bit. Feel free to rollback if it is not okay.
    – peterh
    Commented Dec 14, 2017 at 8:19
  • @peterh Thanks for the edit! I will keep it in mind for future answers.
    – Amit Singh
    Commented Dec 14, 2017 at 9:15
  • +1. Thanks a lot for your answer. The first part works perfectly. The second part together with this specification explaining which values are assumed if the environment variables are not set explains why Thunar is returned.
    – jakun
    Commented Dec 15, 2017 at 7:31
  • 1
    However, I still can not retrace why Nautilus is started because it is not specified in a mimeapps.list. Can you explain what these associations are in "if after all files are handled, we have not yet found a default application, select the most-preferred application (according to associations) that supports the type"? Do you know a way how to find out which program will be started automatically whitout needing to reimplement this algorithm?
    – jakun
    Commented Dec 15, 2017 at 7:32
8

You may want to consider using dbus to open your file as it is quickly becoming more popular.

The concept of a "default" file manager only really exists if you are solely focused on xdg-mime, however in dbus land, (and indeed the majority of applications out there) the story takes a different twist, and the concept of a "default" file manager ceases to exist.

This is how you open a file (/home/me/path/to/folder/or/file) in the (default?) file manager, using dbus:

dbus-send --session --print-reply --dest=org.freedesktop.FileManager1 --type=method_call /org/freedesktop/FileManager1 org.freedesktop.FileManager1.ShowItems array:string:"file:///home/me/path/to/folder/or/file" string:""

What this command does is to look for any dbus service which implements the org.freedesktop.FileManager1 interface, and calls it with the path to the file you wish to open.

The reason I put a question mark after default is because dbus does not respect the concept of "default" file manager; all it does is send the call to the first service it finds that implements the interface and lets it handle the operation. Now it may be that the application it picks is your "default" file manager, but that's not always a guarantee.

Most modern applications will use dbus by default and then fallback to xdg-mime if the dbus call fails, so this is what I'd suggest you do.


Selecting multiple files

This can be achieved by adding a comma between the file names:

dbus-send --session --print-reply --dest=org.freedesktop.FileManager1 --type=method_call /org/freedesktop/FileManager1 org.freedesktop.FileManager1.ShowItems array:string:"file:///home/me/path/to/folder/or/file1","file:///home/me/path/to/folder/or/file2" string:""

Depending on the file manager that is used by dbus, you may get different behaviour when opening multiple files. Some users have complained that Thunar opens a new window (or new tab) for each file selected.

11
  • This worked on Ubuntu 21.10. But what is the last string:"" part? At first I omitted it and that caused an error. Commented Apr 29, 2022 at 12:36
  • @DamnVegetables the last part corresponds to a startup id as you can see here. I couldn't really find anything regarding how it is meant to be used, but I used the empty string because that's exactly what firefox uses when it sends the dbus message. You can observe this for yourself by running the following command in a separate terminal and trying to open a file location from firefox: dbus-monitor interface=org.freedesktop.FileManager1
    – smac89
    Commented Apr 29, 2022 at 16:36
  • 1
    @MikkoRantalainen yes, you can use the syntax array:string"file:///home/me/path/to/folder/or/file1","file:///home/me/path/to/folder/or/file2". Basically add a comma between the file names, and quote them. I added an example
    – smac89
    Commented Feb 19 at 16:58
  • 1
    @MikkoRantalainen sounds like a good time to open a feature request for thunar. Having looked at how other file managers like nemo, and nautilus implement this, it is clear that there isn't a lot out there that get it right, apart from Dolphin
    – smac89
    Commented Feb 21 at 21:33
  • 1
    @MikkoRantalainen yea dolphin does reuse existing windows, but only if the files to select have the same parent folder as any of those existing windows.
    – smac89
    Commented Feb 23 at 2:58
1

@smac89, I wrote an AWK script using your string and saved it to ~/.local/bin/xdg-select-file for opening directories and selecting files for any paths/URIs with GIO binary for getting their URIs. The Syntax of this script is:

xdg-select-file /full/path/file

or:

xdg-select-file ../relative/path/file

or:

xdg-select-file file:///URI%20TO/path/file

You may use single or double quotes for the file path.

And this is code:

#!/usr/bin/awk -f
BEGIN{
    for(i=1;i<ARGC;i++){
        xdg_select_file(ARGV[i])
    }
}

function xdg_select_file(infile,    cmd_get,cmd_run){
    cmd_get="LC_MESSAGES=C gio info " infile
    while((cmd_get|getline)>0){
        if($1~/^uri:/){
        cmd_run="dbus-send --session --print-reply --dest=org.freedesktop.FileManager1 --type=method_call /org/freedesktop/FileManager1 org.freedesktop.FileManager1.ShowItems array:string:\""$2"\" string:\"\""
        break
        }
    }
    system(cmd_run)
    close(cmd_run)
}
0

Use gdbus; this also allows to open the file manager even if filepath or filename contains comma and so doesn't work in dbus-send.

Example:

FILE="path to file/file" #contains comma

gdbus call --session --dest org.freedesktop.FileManager1 --object-path /org/freedesktop/FileManager1 --method org.freedesktop.FileManager1.ShowItems "['file://$FILE']" ""
0

In theory, you should be able to following for both files and directories:

#!/bin/bash
# Copyright 2024 Mikko Rantalainen <[email protected]>
# License: MIT <https://opensource.org/license/mit/>
set -e

urlencode()
{
    printf "%s" "$@" | perl -pe 's/([^A-Za-z0-9.\/:])/sprintf("%%%02X", ord($1))/seg'
}

if test -z "$1"; then
    exec xdg-open .
fi

PREFIX=""
FILES=""
for f in "$@"; do
    abs="$(realpath -e "$f")"
    ef="$(urlencode "$abs")"
    bef="$(printf "file://%q" "$ef")"
    FILES="$FILES$PREFIX$bef"
    PREFIX=","
done

dbus-send --session --dest=org.freedesktop.FileManager1 --type=method_call /org/freedesktop/FileManager1 org.freedesktop.FileManager1.ShowItems array:string:$FILES string:''

However, in practice this works well for one file only and the destination may or may not be your expected file manager. You can change the --dest to match your expected file manager if multiple implement the interface org.freedesktop.FileManager1. For example, if you use Caja, then you could use --dest=org.mate.Caja instead of --dest=org.freedesktop.FileManager1. You can try listing possible destination names with busctl or qdbus.

I'd expect the file manager to select multiple files in a single window when passed multiple files. For my system, only Caja and Thunar seem to implement this API and both implement multiple files by opening equally many windows and selecting one file per window. For a single file or directory, this will result in the expected behavior of opening a file manager window with the given file or directory preselected.

If this script is called without parameters, it will open the current working directory in file manager using xdg-open.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .