我来自 MacOS 系统,在该系统中,我沉迷于一种特定功能:在(几乎)任何应用程序中处理(几乎)任何文件时,我可以单击显示该文件的窗口的标题栏,然后打开文件系统中该文件的父文件夹。
在 MacOS 中,这是一项适用于几乎所有应用程序的功能,并且它基于操作系统和(大多数)为该操作系统编写的应用程序之间的相互作用。
我想在 Linux 系统上有类似的东西(我使用 Mint,带有 Cinnamon 桌面环境)。
我知道也许我需要编写一些脚本,并且可能描述了部分解决方案在这个 U&L 问题/答案中。仍然缺少的是获取文件路径的方法。
因此,我需要的最少功能是(快速)获取我正在可视化的文档的文件路径,同时我处于打开文档窗口的 GUI 应用程序中。
感谢您的任何见解。
答案1
请检查在由另一个应用程序打开的文件上打开文件资源管理器。我是这个问题的OP。菜单的答案是被接受的。这里是完整的解决方案。但是,要了解其工作原理,您必须彻底阅读所引用的帖子。
创建以下脚本(为其提供适当的权限)并将其绑定到键盘快捷键(我已将其绑定到Super key + O),假设脚本名称为open-file-path.sh
。现在,当您在 evince(它具有单个窗口的单个进程,并且可以通过命令找到文件的路径ps
)之类的 gui 应用程序上使用键盘快捷键并打开某些文件时,该文件很可能会在文件资源管理器中打开。
#!/bin/bash
WINDOW_ID=$(xdotool getactivewindow)
PID_OF_ACTIVE_WINDOW=$(xdotool getwindowpid $WINDOW_ID)
CLASS_NAME=$(xprop -id $WINDOW_ID | rg WM_CLASS | cut -d '"' -f2)
if [ "$CLASS_NAME" = "com.github.johnfactotum.Foliate" ]; then
log=$HOME/.myfoliate.log
# nemo "$(awk -v var="$WINDOW_ID" '$1 == var {print}' $log | cut -d" " -f3-)"
nemo "$(grep -oP "$WINDOW_ID $PID_OF_ACTIVE_WINDOW \K.*" $log)"
exit 1
fi
if [ "$CLASS_NAME" = "libreoffice" ]; then
log=$HOME/.mylibreoffice.log
# nemo "$(awk -v var="$WINDOW_ID" '$1 == var {print}' $log | cut -d" " -f3-)"
nemo "$(grep -oP "$WINDOW_ID $PID_OF_ACTIVE_WINDOW \K.*" $log)"
exit 1
fi
if [[ "$CLASS_NAME" == @(gl) ]] ; then
nemo "$(echo '{ "command": ["get_property", "path"] }' | socat - /tmp/mpv-socket | jq -r ".data")"
exit 1
fi
MY_COMMAND_PATH=$(ps -p $PID_OF_ACTIVE_WINDOW -o command)
# https://stackoverflow.com/q/76028252/1772898
if printf -- '%s\n' "$MY_COMMAND_PATH" | grep -qoP '(file://)?(?<!\w)/(?!usr/).*?\.\w{3,4}+'; then
nemo "$(printf -- '%s\n' "$MY_COMMAND_PATH" | grep -oP '(file://)?(?<!\w)/(?!usr/).*?\.\w{3,4}+')"
fi
需要明确的是,标准是:
- 单个进程对应于单个窗口
ps
可以通过命令找到文件的路径
对于不符合标准的其他应用程序(如 libreoffice、foliate 等),还有一些额外的步骤。即使执行了额外的步骤,他们也会遇到一些问题。如果您使用文件 > 打开应用程序中的选项。您必须双击才能打开该文件。如果这些应用程序公开一些内部 api 来提供文件路径(例如,对于 mpv,我们使用内部 api),则可以解决此问题。
我们先讨论mpv。默认情况下它就会起作用。它符合标准。
- 单个进程对应于单个窗口
ps
可以通过命令找到文件的路径
你只需要删除
if [[ "$CLASS_NAME" == @(gl) ]] ; then
nemo "$(echo '{ "command": ["get_property", "path"] }' | socat - /tmp/mpv-socket | jq -r ".data")"
exit 1
fi
从open-file-path.sh
。
但就我而言,我做了一些更改,以便始终有一个窗口,这就是我需要此解决方法的原因。
在我关于 mpv 的情况下,你必须创建一个套接字。加入。input-ipc-server=/tmp/mpv-socket
$HOME/.config/mpv/mpv.conf
然后我们必须为 mpv 可执行文件创建一个包装器。对于桌面应用程序,我们使用该.desktop
文件。对于 mpv 来说,是/usr/share/applications/mpv.desktop
。由于我们必须编辑它,我喜欢放置它的副本$HOME/.local/share/applications/mpv.desktop
,然后编辑该副本。$HOME/.local/share/applications
优先于/usr/share/applications
.
cp /usr/share/applications/mpv.desktop $HOME/.local/share/applications/mpv.desktop
然后更改以下行$HOME/.local/share/applications/mpv.desktop
TryExec=mpv
Exec=mpv --player-operation-mode=pseudo-gui -- %U
和
TryExec=/home/ismail/.dotfiles/.resources/bash-scripts/mpv.sh
Exec=/home/ismail/.dotfiles/.resources/bash-scripts/mpv.sh %U
该/home/ismail/.dotfiles/.resources/bash-scripts/mpv.sh
文件如下所示:
#!/bin/bash
socat_to_mpv() {
socat - "/tmp/mpv-socket"
}
if pgrep -x mpv >/dev/null ; then
wmctrl -x -R gl.mpv
echo "{ \"command\": [\"loadfile\", \"$1\", \"replace\"] }" | socat_to_mpv
else
mpv "$1"
fi
这是包装纸代码。我们在启动 mpv 之前和/或之后运行一些代码。
对于 Foliate,在文件$HOME/.local/share/applications/com.github.johnfactotum.Foliate.desktop
(我从 复制/usr/share/applications/
,如 mpv)中替换Exec
为:
Exec=/home/ismail/.dotfiles/.resources/bash-scripts/foliate.sh %U
该foliate.sh
文件如下所示:
#!/bin/bash
log=$HOME/.myfoliate.log
file=$1
com.github.johnfactotum.Foliate "$1" &
sleep 2
for id in $(xdotool search --onlyvisible --class 'com.github.johnfactotum.Foliate')
do
winpid=$(xdotool getwindowpid $id)
winname=$(xdotool getwindowname $id)
grep -q "^$id $winpid .*" $log || echo "$id $winpid $file" >> $log
done
pid_of_foliate=$(xdotool search --name 'com.github.johnfactotum.Foliate' getwindowpid)
if [ -n "$pid_of_foliate" ]
then
awk -i inplace -v var="$pid_of_foliate" '$2 == var {print}' $log
fi
对于 libreoffice,在以下文件中(我从 复制/usr/share/applications/
,如 mpv):
$HOME/.local/share/applications/libreoffice-calc.desktop
$HOME/.local/share/applications/libreoffice-draw.desktop
$HOME/.local/share/applications/libreoffice-impress.desktop
$HOME/.local/share/applications/libreoffice-writer.desktop
用。。。来代替Exec
:
Exec=/home/ismail/.dotfiles/.resources/bash-scripts/libreoffice.sh --calc %U
Exec=/home/ismail/.dotfiles/.resources/bash-scripts/libreoffice.sh --draw %U
Exec=/home/ismail/.dotfiles/.resources/bash-scripts/libreoffice.sh --impress %U
Exec=/home/ismail/.dotfiles/.resources/bash-scripts/libreoffice.sh --writer %U
分别。
该libreoffice.sh
文件将如下所示:
#!/bin/bash
log=$HOME/.mylibreoffice.log
file=$2
libreoffice "$1" "$2" &
sleep 2
for id in $(xdotool search --onlyvisible --class 'libreoffice')
do
winpid=$(xdotool getwindowpid $id)
winname=$(xdotool getwindowname $id)
grep -q "^$id $winpid .*" $log || echo "$id $winpid $file" >> $log
done
pid_of_libreoffice=$(xdotool search --class 'libreoffice' getwindowpid)
if [ -n "$pid_of_libreoffice" ]
then
awk -i inplace -v var="$pid_of_libreoffice" '$2 == var {print}' $log
fi
我们的想法是我们不使用很多应用程序。对于我们使用的应用程序,有一些方法可以至少接近我们的预期行为。
笔记:如果脚本的依赖项不存在,请安装它们。特别是你可能需要安装xdotool
.
笔记:我用来nemo
打开文件,但如果您使用其他文件资源管理器,那么您可能必须相应地更改脚本。只需替换nemo
为nautilus
或类似的东西很可能会起作用。
改进领域:
此解决方案不适用于 vscode 等某些应用程序。然而,他们有他们的右键单击 > 打开包含的文件夹选项。
更新1:
我一直在研究一个侏儒扩展让体验变得更好。我在解决这个问题时遇到了一些问题。如果 gnome 善意地公开一项数据(windowID),并更正一项数据(PID),那么这将是一个更好的解决方案。此时此刻,这将是一个黑客。
我在下面的链接中遇到的问题。
https://gitlab.gnome.org/GNOME/gnome-shell/-/issues/6705
https://gitlab.gnome.org/GNOME/gnome-shell/-/issues/6708
https://gitlab.gnome.org/GNOME/glib/-/issues/3016
如果这两个问题得到解决,那么我们希望能够获得一个 gnome 扩展,我们可以使用它“在(几乎)任何应用程序中处理(几乎)任何文件时,使用键盘快捷键,然后在文件系统中打开该文件的父文件夹(当选择该文件时)。”
目前,我不想开发一个 hacky 解决方案,并且我的大部分问题都是通过我上面提到的当前解决方案解决的。
因此,如果这些问题得到解决,请告诉我,希望我能完成工作。
答案2
这将是应用程序的功能,可能通过应用程序使用的 GUI 工具包提供,而不是操作系统或桌面环境的功能。由于您将 Mint 与 Cinnamon 一起使用,因此您可能主要使用 Gnome 应用程序。
在大多数 Gnome 应用程序中,侏儒 ≤3.36(在 Ubuntu 20.04 上测试),以下按键顺序将起作用:Ctrl+O Alt+Up Shift+F10 Return
- Ctrl+O是“打开”命令的常用 Gnome 键盘快捷键。它会打开 Gtk 文件打开对话框。接下来的所有内容都适用于使用此文件打开对话框的任何应用程序。该对话框将在包含当前文件的目录中打开。
- Alt+Up转到当前目录的父目录。选择上一个目录,即您感兴趣的目录。
- Shift+F10调出上下文菜单。
- Return选择上下文菜单上的第一个条目,即“使用文件管理器打开”。
如果用鼠标的话,那就是:
- 选择“打开文件”命令。 (“另存为”也可以。)
- 当前目录的路径显示在顶部,每个目录都在单独的框中。单击右侧第二个框,即当前目录的父目录。
- 右键单击所选条目(即您感兴趣的目录)以显示上下文菜单。
- 在上下文菜单中选择“使用文件管理器打开”。
我不是 Gnome 专家。也许有更方便的方法。
和侏儒≥3.38,不幸的是,这变得更加麻烦,因为文件打开对话框默认显示“最近”列表。要查看包含当前文件的目录,您需要在左侧选项卡中导航到该目录(使用键盘:F6 Down Down...)。然后您可以使用Alt+Up或顶部栏导航到父目录。
和凯特(在 19.12.3 上测试),右键单击选项卡标题中的文件名,然后选择“打开所在文件夹”。