在默认文件管理器中打开一个目录并选择一个文件

在默认文件管理器中打开一个目录并选择一个文件

在我正在编写的程序中,我想提供打开我当前正在处理的文件所在目录并自动选择该文件的功能(以便用户不需要搜索它)。

我知道我可以使用以下命令在默认文件管理器中打开目录

xdg-open /path/to/directory

我知道我可以在 nautilus 中打开一个目录并使用选择一个文件

nautilus /path/to/file.txt

想法我可以用

xdg-mime query default inode/directory

获取默认文件管理器 - 如果是 nautilus - 调用它,如上所示。但是,尽管 nautilus 是我系统上的默认设置(xdg-open在 gnome shell 中打开 nautilus 和位置菜单),但xdg-mime返回Thunar.desktop. (我已经尝试过find / -name Thunar.desktop -mount 2>/dev/null,但没有找到任何东西。)

另外,我不知道如何打开目录并选择子目录目录在 nautilus 中(使用上述方法它将打开子目录)。

如何在默认文件管理器中打开目录在该目录中选择一个文件(如果也可以选择一个目录,那就太好了,但对于这个应用程序来说不需要)或者至少找出默认的文件管理器,以便我可以直接调用它?

答案1

1.要在 nautilus 中打开目录并选择子目录/文件:

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

nautilus(1) 手册页

-s,--选择
  选择父文件夹中指定的 URI。

2. xdg-mime返回Thunar.desktopxdg-open打开nautilus

xdg-mime用于mimeapps.list确定要使用的默认应用程序。

存在单独的mimeapps.list文件来处理特定于用户、特定于系统和特定于发行版的要求。它们的查找顺序可以在这里

mimeapps.list在 [默认应用程序] 部分下列出给定 mimetype 的默认应用程序。它允许按优先级降序列出多个默认应用程序。例如 :

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

在哪里模仿类型1是哑剧类型并且*。桌面是桌面文件。

xdg-open按照查找顺序在首选项列表中搜索桌面文件,直到找到有效的桌面文件。如果在所有文件中都没有找到这样的文件,则根据关联选择最优选的一个文件并将其用作默认应用程序。

因此,在我们的示例中,假设default1.desktop我们的系统上不存在,因此xdg-open将尝试使用default2.desktop.但是,xdg-mime返回的 default1.desktop是我们mimeapps.list文件中的第一个条目。

在你的情况下default1.desktop必须是Thunar.desktop输出。但是它没有安装在您的系统上。因此,使用系统上存在的xdg-open文件/目录打开您的文件/目录。nautilus要验证这一点,您可以检查mimeapps.list文件中包含inode/directory.对于 Ubuntu 17.10,文件的位置mimeapps.list是:/usr/share/applications/defaults.list

笔记:可以找到确定“默认应用程序”的完整算法这里

答案2

您可能需要考虑使用 dbus 打开文件,因为它很快变得越来越流行。

“默认”文件管理器的概念只有在您只专注于 时才真正存在xdg-mime,但是在 dbus 领域(实际上是大多数应用程序),情况会有所不同,并且“默认”文件的概念经理不复存在。

/home/me/path/to/folder/or/file这是使用 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:""

该命令的作用是查找任何实现该org.freedesktop.FileManager1接口的 dbus 服务,并使用您要打开的文件的路径来调用它。

我后面打问号的原因默认是因为 dbus 不尊重“默认”文件管理器的概念;它所做的只是将调用发送到它发现的第一个实现该接口的服务并让它处理该操作。现在它选择的应用程序可能是您的“默认”文件管理器,但这并不总是保证。

大多数现代应用程序将dbus默认使用,然后xdg-mime在 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/file1","file:///home/me/path/to/folder/or/file2" string:""

根据 dbus 使用的文件管理器,打开多个文件时可能会出现不同的行为。一些用户抱怨 Thunar 为每个选定的文件打开一个新窗口(或新选项卡)。

答案3

@smac89,我使用您的字符串编写了一个 AWK 脚本,并将其保存到~/.local/bin/xdg-select-file打开目录并使用 GIO 二进制文件为任何路径/URI 选择文件以获取其 URI。该脚本的语法是:

xdg-select-file /full/path/file

或者:

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

或者:

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

您可以使用单引号或双引号作为文件路径。

这是代码:

#!/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)
}

答案4

理论上,您应该能够对文件和目录执行以下操作:

#!/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:''

然而,实际上,这仅适用于一个文件,并且目标可能是也可能不是您期望的文件管理器。--dest如果多个实现该接口,您可以更改以匹配您期望的文件管理器org.freedesktop.FileManager1。例如,如果您使用 Caja,那么您可以使用--dest=org.mate.Caja代替--dest=org.freedesktop.FileManager1.您可以尝试使用busctl或列出可能的目的地名称qdbus

我希望文件管理器在传递多个文件时在单个窗口中选择多个文件。对于我的系统,似乎只有 Caja 和 Thunar 实现了此 API,并且都通过打开同等数量的窗口并为每个窗口选择一个文件来实现多个文件。对于单个文件或目录,这将导致打开文件管理器窗口并预选给定文件或目录的预期行为。

如果不带参数调用此脚本,它将使用 . 在文件管理器中打开当前工作目录xdg-open

相关内容