有没有办法告诉已经运行的 x 程序从 bash 打开文件?(即不调用程序的新实例。)虽然我是在的背景下提出这个问题的xstata-mp
,但我更感兴趣的是,这种解决方案是否存在一般来说用于 Xorg 应用程序。
我有一个 x 应用程序(xstata-mp
,专有,正如您将了解到的,这对于这个问题很重要),它运行良好。我设法编写了一个不错的启动脚本,它首先检查是否xstata-mp
已经在运行,如果是,则将其置于前台,否则启动它。就像这个问题的可接受答案。
我的问题是,有时我想打开一个文档xstata-mp
被(例如,.dta
数据文件、.do
脚本文件、帮助文件等)使用.sthlp
。如果我双击此类文件的图标,或者选择图标并在运行<ENTER>
时点击xstata-mp
,则启动脚本将被调用(它在文件的部分中引用)exec
并提升到可见窗口的顶部,但不打开文档。xstata-mp
.desktop
xstata-mp
不管怎样,检查pidof
一下xstata-mp
才不是xstata-mp
如果我在其中打开多个文档(例如,使用<CTRL>-O
),则启动一个新流程;Firefox
与多个选项卡/站点形成对比。
这是我想要修改的启动脚本:
# Check if xstata-mp v17 is running
exit_code_pidof_xstata_mp=$(pidof /usr/local/stata17/xstata-mp)
# if xstata-mp v17 IS NOT running, then launch it with argument $1
if [ -z "$exit_code_pidof_xstata_mp" ]
then
/usr/local/stata17/xstata-mp -q $1; exit >/dev/null
# but if xstata-mp v17 IS running, then bring it to front instead
else
wmctrl -ia "$(wmctrl -lp | grep "$(pgrep /usr/local/stata17/xstata-mp)" | tail -1 | awk '{ print $1 }')"; exit > /dev/null
fi
答案1
首先,你应该找到打开文档的正确命令。因此,尝试运行以下命令并查看结果。
/usr/local/stata17/xstata-mp --help
当然这是关键部分。在这里你完全依赖程序的功能。如果它不提供这个选项,那么你就无法做到,因为 bash 所能做的就是启动另一个程序我从 上下载了 9.4 MB 的 399 页用户手册史塔塔公司,没有关于如何使用的提示xstata-mp
。
也许该-q
选项已经是您想要的。但让我们假设将另一个文档添加到已运行的实例的正确选项xstata-mp
是-a
(如在 VS Code 中code -a
:)。那么您所要做的就是在else
语句下方添加以下行:
/usr/local/stata17/xstata-mp -a "$1"
它将打开您的文档并显示当前窗口。
答案2
是的:有一种方法可以告诉已经运行的 x 程序从 bash 打开一个文件!
因此,根据 StataCorp 技术支持人员的提示,结果是xdotool
sudo apt install xdotool
(如果您的系统上还没有安装,可以使用 进行安装)为我的问题提供了一种解决方案。摘自项目网站:
xdotool
让您模拟键盘输入和鼠标活动、移动和调整窗口大小等。它使用 X11 的 XTEST 扩展和其他 Xlib 函数实现这些功能。⚠️ 注意:如果您正在使用 Wayland,请注意该软件将无法正常工作。⚠️
使用
xdotool
,您可以搜索窗口并移动、调整大小、隐藏和修改窗口属性(例如标题)。如果您的窗口管理器支持,您可以使用xdotool
切换桌面、在桌面之间移动窗口以及更改桌面数量。
为了解决我的问题xdotool
,我需要创建一个xdotool
我正在调用的脚本statadoc.xdo
:
#!/usr/bin/xdotool
search --name "Stata/MP"
type --window %1 '$1 ' '$2'
key --window %1 Return
关于这个简短脚本的一些评论:
- 路径可能是 以外的其他路径
/usr/bin/xdotool
,因此请务必确认是否具有which xdotool
或类似的路径。 - 第二行将部分匹配
"Stata/MP 17.0"
上面提供的字符串的名称。这很有用,例如,将版本升级到 17.1 或 18.x 不会破坏脚本。该search
命令标识了我想要与之交互的 X 应用程序窗口。 xdotool
脚本接受参数,遵循bash
类似$1
、$2
等的约定。- 该命令实际上输入了提供的文本 - 在我的例子中,是第 2 行的命令标识的第 1 个窗口中提供的两个文本和字符串参数
type
的内容(在我的例子中也是唯一一个) 。$1
$2
search
- 该
key
命令将<ENTER>
(或<RETURN>
如果您愿意)发送到同一个 Stata 窗口。
现在让我们看一下我修改后的启动脚本,它statadoc.xdo
在倒数第三行调用(我在前面添加了一个部分来识别所提供的参数是否指示特定的 Stata 文件类型 - 需要不同的使用命令来优雅地处理每个...我的例子并不完整,但这些是我在大部分工作中使用的文件类型):
# Check whether there IS NOT an argument. If not, do nothing.
if [ -z "$1" ]
then
break
# Otherwise, set prefix to default value, and then check
# whether file name ends in .hlp, .sthlp, .ado, .do, or .gph
else
prefix="use "
if [ ${1##*.} = "hlp" ] || [ ${1##*.} = "sthlp" ] || [ ${1##*.} = "ado" ] || [ ${1##*.} = "do" ]
then
# If the filename DOES end in one of those four prefixes then
# change prefix to "doedit" so Stata opens the document with
# the do-file editor.
prefix="doedit "
fi
# If the filename ends in .gph, then change prefix to "doedit" so
# Stata opens the document with the graph viewer/editor.
if [ ${1##*.} = "gph" ]
then
prefix="graph use "
fi
break
fi
# Check if xstata-mp v17 is running
exit_code_pidof_xstata_mp=$(pidof /usr/local/stata17/xstata-mp)
# if xstata-mp v17 IS NOT running, then launch it with argument $1
if [ -z "$exit_code_pidof_xstata_mp" ]
then
/usr/local/stata17/xstata-mp -q $1; exit >/dev/null
# but if xstata-mp v17 IS running, then bring it to front instead
else
# First, call statadoc.xdo with the prefix as the first argument,
# and the supplied file path as the second argument
/usr/share/stata17/bin/statadoc.xdo "$prefix" " $1"
wmctrl -ia "$(wmctrl -lp | grep "$(pgrep /usr/local/stata17/xstata-mp)" | tail -1 | awk '{ print $1 }')"; exit > /dev/null
fi
注意:这是在 Xorg 上运行 Gnome 的解决方案。