在终端中运行 .desktop 文件

Mal*_*rba 190 command-line shortcuts .desktop

据我所知,.desktop文件是允许自定义应用程序设置的快捷方式。例如,我的/usr/share/applications/文件夹中有很多。

如果我在 中打开该文件夹nautilus,则只需双击其关联文件即可运行这些应用程序,例如双击firefox.desktop运行 Firefox。但是,我找不到通过终端做同样事情的方法。

如果我这样做,gnome-open foo.desktop它只是foo.desktop作为文本文件打开。如果我使它可执行,然后在 bash 中运行它,它只会失败(这是意料之中的,它显然不是 bash 脚本)。
编辑:做exec /fullpath/foo.desktop给我一个Permission denied信息,即使我改变了自己的所有权。如果我使可执行文件并执行相同的命令,我正在使用的终端选项卡就会关闭(我猜它会崩溃)。最后,如果我这样做sudo exec /fullpath/foo.desktop,我会收到错误报告sudo: exec: command not found

这是我的问题,如何foo.desktop从终端运行文件?

dou*_*oug 113

gtk-启动

使用任何支持的最新 Ubuntu,gtk-launch只需简单地去

gtk-launch <file>
Run Code Online (Sandbox Code Playgroud)

带或不带部件<file>.desktop文件名在哪里.desktop。名称不得包含完整路径。

.desktop文件必须在/usr/share/applications,/usr/local/share/applications~/.local/share/applications.

因此gtk-launch foo打开/usr/share/applications/foo.desktop(或foo.desktop位于其他允许的目录之一中。)

gtk-launch 文档

gtk-launch使用给定的名称启动应用程序。除非另有说明,否则应用程序会在默认显示器上以正确的启动通知启动。

gtk-launch至少接受一个参数,即要启动的应用程序的名称。该名称应与驻留在 /usr/share/application 中的应用程序桌面文件名匹配,带有或不带有“.desktop”后缀

可从终端使用或Alt + F2Alt + F2将命令存储在历史记录中,以便于访问)。

  • 在 Ubuntu 18.10 上没有任何版本对我有用。每次它抱怨应用程序不存在时,无论我是否在包含桌面文件的文件夹中,是否包含 .desktop 扩展名,以及是否单独命名目录。 (5认同)
  • @JosephGarvin 好吧,我明白了,它是 gtk-launch MYCUSTOMAPP.desktop ,没有路径。适用于 ubuntu 18.10 (2认同)

Ric*_*way 100

答案应该是

xdg-open program_name.desktop
Run Code Online (Sandbox Code Playgroud)

但由于一个bug此处上游)此不再有效。

  • “不再有效”?它从来没有!`xdg-open` 通过 mimetype 关联工作,并且 `.desktop` 文件与文本编辑器相关联,因为它们是文本的子类 (17认同)
  • 这太愚蠢了(没有明智的方法可以从终端运行桌面文件) (15认同)
  • 哇这仍然是一个错误,xdg 有很多进步。`exo-open` 被列为解决方法,它也会打开 gedit。:( (8认同)
  • 目前这在 Arch Linux 中对我不起作用。`xdg-open program_name.desktop` 在文本编辑器中打开桌面文件。 (3认同)
  • 在 Arch Linux 上对我有用,但可能是 Ubuntu 特定的错误。 (2认同)

Ham*_*ner 79

现代答案

gtk-launch <app-name>-<app-name>文件的文件名.desktop,带或不带.desktop扩展名。

有关更多详细信息,请参阅此线程上的另一个答案我从那个答案中得到了这个信息。

弃用的 shell 工具答案

很久以前写的 - 请参阅此答案下方的评论,了解为什么这种方法不适用于许多桌面文件。

运行的命令包含在桌面文件中,前面是Exec=这样,您可以通过以下方式提取并运行它:

$(grep '^Exec' filename.desktop | tail -1 | sed 's/^Exec=//' | sed 's/%.//' \
| sed 's/^"//g' | sed 's/" *$//g') &
Run Code Online (Sandbox Code Playgroud)

打破它

grep  '^Exec' filename.desktop    # - finds the line which starts with Exec
| tail -1                         # - only use the last line, in case there are 
                                  #   multiple
| sed 's/^Exec=//'                # - removes the Exec from the start of the line
| sed 's/%.//'                    # - removes any arguments - %u, %f etc
| sed 's/^"//g' | sed 's/" *$//g' # - removes " around command (if present)
$(...)                            # - means run the result of the command run 
                                  #   here
&                                 # - at the end means run it in the background
Run Code Online (Sandbox Code Playgroud)

你可以把它放在一个文件中,比如~/bin/deskopen内容

#!/bin/sh
$(grep '^Exec' $1 | tail -1 | sed 's/^Exec=//' | sed 's/%.//' \
| sed 's/^"//g' | sed 's/" *$//g') &
Run Code Online (Sandbox Code Playgroud)

然后让它可执行

chmod +x ~/bin/deskopen
Run Code Online (Sandbox Code Playgroud)

然后你可以做,例如

deskopen /usr/share/applications/ubuntu-about.desktop
Run Code Online (Sandbox Code Playgroud)

该参数(%u%F等等)中详细介绍在这里。它们都与在命令行启动无关。

  • -1:这可能适用于简单的“.desktop”文件,但它会忽略可能影响执行的“Path=”和“TryExec=”等条目。如果文件包含桌面操作(“快速列表”),它也会执行错误的 `Exec=` (15认同)

小智 40

该错误自 2006 年以来仍然存在。它实际上取决于gvfs-open(由 调用xdg-open)的工作方式。

尽管如此,我还是设法快速解决了(从 nautilus 源代码中窃取灵感)。它有点复杂,但在 Ubuntu 12.10 上运行完美?,在 Unity 启动器上添加了一个有意义的图标(不再是)。

首先,我使用 Gio 编写了一个 python 脚本并将其保存为~/bin/run-desktop

#!/usr/bin/python

from gi.repository import Gio
import sys 

def main(myname, desktop, *uris):
    launcher = Gio.DesktopAppInfo.new_from_filename(desktop)
    launcher.launch_uris(uris, None)

if __name__ == "__main__":
    main(*sys.argv)
Run Code Online (Sandbox Code Playgroud)

该脚本需要具有可执行权限,所以我在终端中运行了它:

chmod +x ~/bin/run-desktop
Run Code Online (Sandbox Code Playgroud)

然后我创建了相对.desktop条目~/.local/share/applications/run-desktop.desktop

[Desktop Entry]
Version=1.0
Name=run-desktop
Exec=run-desktop %U
MimeType=application/x-desktop
Terminal=false
Type=Application
Run Code Online (Sandbox Code Playgroud)

最后,我将条目关联~/.local/share/applications/mimeapps.list为该[Default Applications]部分下的默认处理程序:

[Default Applications]
....
application/x-desktop=run-desktop.desktop
Run Code Online (Sandbox Code Playgroud)

现在:

  • xdg-open something.desktop 按预期工作
  • #!/usr/bin/xdg-open 可执行桌面条目顶部的 hashbang 也可以工作

什么时候gvfs-open解决这个错误将是无用的工作,但与此同时......

  • 感谢您的代码 - 我在 Lucid,我只是将它保存为 `/usr/bin/xdg-openpy`,并给它一个 `chmod +x` - 并使用了 `launcher.launch([],context) ` 而不是 `...None,context)`(因为“_TypeError:参数 1:必须是序列,而不是 NoneType_”)。现在`xdg-openpy app.desktop`可以从命令行工作(双击`app.desktop`时一切正常),如果我尝试调用终端`xdg-open`并按Tab键,它会提醒我。干杯! (4认同)
  • +1。这是唯一不需要手动解析 `.desktop` 文件的答案,因此它是最明智(和安全)的方法。还使用现代的 `gi.repository` 而不是弃用的 `pygtk`,太棒了!:) (4认同)
  • *事实上,这是一个关于 Carlo Pellegrini 回答的问题。我是新手,如果有更好的放置方式,请纠正我。* 脚本工作得很好,但我在 Unity 启动器上看到的图标不是 .desktop 文件中定义的图标,而是默认图标'Exec'ed 命令。对此有什么想法吗? (2认同)

Six*_*Six 37

正确的方式

gtk-launch如果可用,您真的应该使用它。它通常是libgtk-3-bin包的一部分(这可能因发行版而异)。

gtk-launch 用法如下:

gtk-launch APPLICATION [URI...]
gtk-launch app-name.desktop
gtk-launch app-name
Run Code Online (Sandbox Code Playgroud)

请注意,gtk-launch需要安装.desktop文件(即位于/usr/share/applications~/.local/share/applications)。

因此,为了解决这个问题,我们可以使用一个 hackish 小 Bash 函数,在启动它之前临时安装所需的.desktop文件。安装.desktop文件的“正确”方法是通过desktop-file-install但我将忽略它。

launch(){

    # Usage: launch PATH [URI...]

    # NOTE: The bulk of this function is executed in a subshell, i.e. `(..)`
    #       This isn't strictly necessary, but it keeps everything
    #       out of the global namespace and lessens the likelihood
    #       of side effects.

    (

    # where you want to install the launcher to
    appdir=$HOME/.local/share/applications

    # the template used to install the launcher
    template=launcher-XXXXXX.desktop

    # ensure $1 has a .desktop extension, exists, is a normal file, is readable, has nonzero size
    # optionally use desktop-file-validate for stricter checking
    # desktop-file-validate "$1" 2>/dev/null || {
    [[ $1 = *.desktop && -f $1 && -r $1 && -s $1 ]] || {
        echo "ERROR: you have not supplied valid .desktop file" >&2
        return 1
    }

    # ensure the temporary launcher is deleted upon exit
    trap 'rm "$launcherfile" &>/dev/null' EXIT

    # create a temp file to overwrite later
    launcherfile=$(mktemp -p "$appdir" "$template")

    launchername=${launcherfile##*/}

    # overwrite temp file with the launcher file
    if cp "$1" "$launcherfile" &>/dev/null; then
        gtk-launch "$launchername" "${@:2}"
    else
        echo "ERROR: failed to copy launcher to applications directory" >&2
        return 1
    fi

    )

}
Run Code Online (Sandbox Code Playgroud)

您可以像这样使用它(如果需要,还可以传递其他参数或 URI):

launch PATH [URI...]
launch ./path/to/shortcut.desktop
Run Code Online (Sandbox Code Playgroud)

手动替代方案

如果要手动解析和执行.desktop文件,可以使用以下awk命令执行此操作:

awk '/^Exec=/ {sub("^Exec=", ""); gsub(" ?%[cDdFfikmNnUuv]", ""); exit system($0)}' app-name.desktop
Run Code Online (Sandbox Code Playgroud)

如果你想把awk命令当作一个多合一的脚本;如果找不到Exec命令,我们甚至可以显示错误消息并以返回码 1 退出:

awk 'BEGIN {command=""} /^Exec=/ {sub("^Exec=", ""); gsub(" ?%[cDdFfikmNnUuv]", ""); command=$0; exit} END {if (command!="") {exit system(command)} else {if (FILENAME == "-") {printf "ERROR: Failed to identify Exec line\n" > "/dev/stderr"} else {printf "ERROR: Failed to identify Exec line in \047%s\047\n", FILENAME > "/dev/stderr"} close("/dev/stderr"); exit 1}}'
Run Code Online (Sandbox Code Playgroud)

上述命令将:

  1. 找到以Exec=开头的行
  2. 删除执行=
  3. 删除任何 Exec 变量(例如%f, %u, %U)。可以按照规范的意图用位置参数替换这些参数,但这样做会显着增加问题的复杂性。请参阅最新的桌面入门规范
  4. 执行命令
  5. 立即以适当的退出代码退出(以免执行多个Exec行)

请注意,此 AWK 脚本解决了一些其他一些答案可能会或可能不会正确解决的边缘情况。具体来说,此命令删除多个Exec变量(注意不要以其他方式删除 % 符号),只会执行单个Exec行命令,并且即使Exec行命令包含一个或多个等号(例如script.py --profile=name),也会按预期运行。

只是其他一些警告......根据规范,TryExec是:

磁盘上可执行文件的路径,用于确定程序是否已实际安装。如果路径不是绝对路径,则在 $PATH 环境变量中查找文件。如果该文件不存在或不可执行,则该条目可能会被忽略(例如,不能在菜单中使用)。

考虑到这一点,执行它的价值是没有意义的。

其他一些问题是PathTerminal路径由运行程序的工作目录组成。终端是一个布尔值,指示程序是否在终端窗口中运行。这些都可以解决,但是重新发明轮子是没有意义的,因为已经有规范的实现。如果您确实想实现Path,请记住它会system()生成一个子进程,因此您无法通过执行类似system("cd \047" working_directory "\047"); system(command). 但是你大概可以做类似的事情system("cd \047" working_directory "\047 && " command)。注意 \047 是单引号(因此该命令不会在带有空格的路径上中断)。

Python替代品

我在这里从 Carlo那里窃取了一个页面,他建议创建一个 Python 脚本来使用gi模块。这是从 shell 执行相同代码而无需创建文件和担心 I/O 的最小方法。

launch(){

# Usage: launch PATH [URI...]

python - "$@" <<EOF
import sys
from gi.repository import Gio
Gio.DesktopAppInfo.new_from_filename(sys.argv[1]).launch_uris(sys.argv[2:])
EOF

}
Run Code Online (Sandbox Code Playgroud)

然后执行启动器功能如下:

launch ./path/to/shortcut.desktop
Run Code Online (Sandbox Code Playgroud)

请注意,URI 的使用是可选的。此外,不执行错误检查,因此如果您希望脚本持久,您需要确保启动器存在并且可读(在使用它之前)。


Ram*_*man 35

虽然 OP 没有询问 KDE,但对于运行 KDE 的任何人,都可以使用以下命令:

kioclient exec <path-to-desktop-file>

在 Fedora 上,这包含在kde-runtimerpm 中。

  • 赞成,因为它有效。根本不需要运行 KDE,只要你安装了这个程序。 (5认同)
  • `kioclient5 exec ~/.local/share/applications/myprogram.desktop` 在 Kubuntu 20.04 上为我工作 (3认同)

小智 31

你可以使用dex

dex foo.desktop
Run Code Online (Sandbox Code Playgroud)

  • 恕我直言,这正是正确的答案:一个工具,一个只有文件作为参数的调用。这也是我一直在寻找的,以测试手写的“.desktop”文件。它也可以创建`.desktop` 文件,耶!:-) (4认同)
  • 就是这样!太多滚动以获得正确的答案... (2认同)

jar*_*rno 18

exo-open [[path-to-a-desktop-file]...]
Run Code Online (Sandbox Code Playgroud)

如果安装了 exo-utils(就像 Xubuntu 的情况),它似乎在 13.10 版本中工作。


pab*_*bst 9

哈米什回答的附录。

给定deskopen 脚本,您可以使用对它的引用作为.desktop文件中的shebang 行,因为注释字符仍然是#。也就是说,把这个作为.desktop文件的第一行:

#!/usr/bin/env deskopen
Run Code Online (Sandbox Code Playgroud)

然后将.desktop文件标记为可执行文件(例如使用chmod +x whatever.desktop),然后您就可以

path/to/whatever.desktop
Run Code Online (Sandbox Code Playgroud)

-应用程序将打开!(完成我指定的图标文件,虽然我不知道如何。)

现在,如果您还希望deskopen 传递任何命令行参数,您可以改用这个稍微修改的版本:

#!/bin/sh
desktop_file=$1
shift
`grep '^Exec' "${desktop_file}" | sed 's/^Exec=//' | sed 's/%.//'` "$@" &
Run Code Online (Sandbox Code Playgroud)

顺便说一句,我尝试使用"#{@:2}"而不是shifting,但它一直给我“糟糕的替代”......

  • 这本身就是一个答案,很好。 (2认同)

Gab*_*les 9

(从这里的各种其他答案编译)

根据您的系统以及系统上可能存在或不存在的各种错误,请尝试以下操作,直到其中一个正常工作:

  1. xdg-open program_name.desktop
  2. exo-open program_name.desktop [我的首选,只要它有效]
  3. gtk-launch program_name.desktop
  4. kioclient exec program_name.desktop
  5. dex program_name.desktop
  6. 或者,这是来自@Hamish Downer 的命令,grep在 *.desktop 文件中搜索Exec=包含要执行的命令的行,删除我们不想要的那行部分,然后执行它。它写得很好,适用于大多数桌面文件。有关它的完整解释,请参阅他的回答
    # To execute the `Exec=` cmd from filename.desktop in the background
    $(grep '^Exec' filename.desktop | tail -1 | sed 's/^Exec=//' \
    | sed 's/%.//' | sed 's/^"//g' | sed 's/" *$//g') &
    
    # Or, remove the `&` at the end to execute it in the foreground so you 
    # can see output from running the command too
    $(grep '^Exec' filename.desktop | tail -1 | sed 's/^Exec=//' \
    | sed 's/%.//' | sed 's/^"//g' | sed 's/" *$//g')
    
    Run Code Online (Sandbox Code Playgroud)

请注意,在 Ubuntu 系统上,您的“开始菜单”桌面启动器在/usr/share/applications/.

例如,要显示上述哪些命令在我的 Ubuntu 14.04 系统上有效或无效,以下是对我的以下调用的结果:

  1. xdg-open /usr/share/applications/eclipse_for_cpp.desktop # 由于错误而失败(试图让我保存这个 .desktop 文件)
  2. exo-open /usr/share/applications/eclipse_for_cpp.desktop #作品
  3. gtk-launch /usr/share/applications/eclipse_for_cpp.desktop # 以“gtk-launch: no such application”失败
  4. kioclient exec /usr/share/applications/eclipse_for_cpp.desktop #作品
  5. dex /usr/share/applications/eclipse_for_cpp.desktop# 失败,sudo apt install dex无法定位包 dex
  6. $(grep '^Exec' /usr/share/applications/eclipse_for_cpp.desktop | tail -1 | sed 's/^Exec=//' | sed 's/%.//' | sed 's/^"//g' | sed 's/" *$//g') & #作品


sla*_*den 7

我没有立即满足“使用标准命令”要求的解决方案,但是如果您确实想要最少地解析.desktop文件或想要创建 Bash 别名,那么以下方法应该可行:

  • awk -F= '/Exec=/{system($2); exit}' foo.desktop

另一种可能有趣的方法是创建一个内核级binfmt-misc方法而不是.desktop文件匹配(请参阅grep -r . /proc/sys/fs/binfmt_misc/您当前已启用的那些模式)。

在一天结束的时候,一些地方将要解析.desktop的文件,这是多么的“标准/默认”这是一个问题。


Emm*_*ory 6

目前没有一个应用程序可以执行您在 Ubuntu 档案中描述的内容。正在努力创建通用解决方案,为不符合这些 XDG 规范的桌面环境(如 openbox)提供集成。

Arch Linux 正在开发基于 python-xdg 库的 xdg-autostart 实现。据我所知,这似乎还没有完全完成,但有一些成功的报告。

在 gitorious (http://gitorious.org/xdg-autostart/) 上还有一个 xdg-autostart 的 C++ 实现,它可能会从更广泛的使用中受益。

如果任一解决方案适合您,请考虑提交必要的工作以包含在 Debian 或 Ubuntu 中。

要在 openstart 中使用任一工具,您可以在 /etc/xdg/openbox/autostart.sh 中调用它(如果我正确阅读了 openbox 文档)。如果这不起作用,您可以在任何 openbox 会话初始化脚本中调用它。