我试图获取我在 zathura 查看器中打开的每个 PDF 的完整路径。我知道这是可能的,因为有了rofi -show window
,我可以看到完整的路径。
我尝试过跑步
ps -p $(pgrep zathura) -o command
但是,这只显示部分名称,具体取决于我打开 PDF 时所在的位置。
情况变得更糟,当我使用 Vimtex 时,在这种情况下,它会显示类似的内容
zathura -x /usr/bin/nvim --headless -c "VimtexInverseSearch %{line} '%{input}'" --synctex-forward 224:1:/Path/to/part.tex main.pdf
其中 main.pdf 不需要与 part.tex 位于同一位置(如果您使用 \include 等,则会发生这种情况)。
一旦获得收益,rofi就做对了!
我可能可以编写一个“复杂”的脚本,该脚本将在part.tex文件的每个父目录中递归搜索以找到main.pdf文件...
有谁知道rofi是怎么做的吗?或者更重要的是,我该怎么做?
我在用
X11服务器
Arch Linux,6.2.8-arch1-1
GNU bash,版本 5.1.16
罗菲版本:1.7.5
扎图拉版本 0.5.2
谢谢大家。
答案1
尝试这样的事情:
pids=( $(pgrep zathura) )
for p in "${pids[@]}"; do
mapfile -d '' -t pdfs < <(
find "/proc/$p/fd/" -lname '*.pdf' -printf '%l\0')
[ -n "$pdfs" ] && echo "$p: ${pdfs[@]}"
done
首先构建一个$pids
包含所有进程 PID 的数组 ( ) zathura
。
然后,对于每个 PID,它在 /proc/PID/fd 目录中查找以 结尾的符号链接目标,.pdf
并构建一个$pdfs
匹配数组 ( )。两者都mapfile
使用find
NUL 作为文件名分隔符,因此它可以正确处理任何文件名(即使是那些包含空格、换行符和 shell 元字符等烦人字符的文件名)。
最后,如果$pdfs
数组不为空,它将打印 PID 和数组。例如
3289895: /home/cas/Manuals/X399 Taichi.pdf
3290171: /home/cas/Manuals/Define R5 Web-manual V1.2_151013.pdf
注意:这不是便携式的。它仅适用于 Linux(因为 /proc/PID/fd - /proc 伪文件系统特定于 Linux)。
另请注意:当我搜索atril
或qpdfview
进程时,这对我来说非常有效,但当我搜索进程时失败(由于权限错误)zathura
。
我不知道为什么,但在我的系统上,/proc/PID/fd/
atril 和 qpdfview PID 的目录由 拥有cas
,但 zathura PID 的 fd/ 目录由 root 拥有,并且只能由 root 读取。
诡异的。我不知道这是否是我的系统(Debian Sid)的一些奇怪的特性,或者是 zathura 的一些奇怪的东西。
(更新:事实证明确实如此zathura
。请参阅zathura 和 /proc/PID 中文件的所有权)
当然,如果我跑步sudo find ...
而不是仅仅find
在流程替代。
顺便说一句,除非您已经sudo
配置为允许您的用户帐户以 root 身份运行任何内容,否则我不建议将其配置为允许find
以 root 身份运行。 find
有一个-exec
谓词,可用于运行任何事物。
相反,编写一个仅需要两个参数的包装器脚本:
- PID,以及
-lname
谓词作为参数进行匹配的模式。
它应该检查 PID arg 是否只包含数字,并且 /proc/PID 目录属于$SUDO_USER
,然后find
使用大部分硬编码的 args 运行。配置sudo
以允许您的用户运行该脚本。
无论如何,这就是sudo
使用方式 - 编写非常受限制的、单一用途的包装脚本,并进行极其偏执的输入检查,只做一件事。作为 root 执行的操作越少越好。
这是一个非常原始的例子。它的意思是最小的理论的仅作为示例,不使用没有仔细的测试和认真的尝试来“打破”它。说真的,我花了大约 2 分钟写这篇文章,它不应该被信任——这远远不够时间来考虑和反驳这个包装脚本可能被破坏的每一种可能的方式。
#!/bin/bash
# Arguments:
# $1 PID to examine
# $2 pattern to match -lname (symlink target)
#
# Returns NUL-separated list of matching symlink
# targets found in /proc/$1/fd/
[ "$#" -ne 2 ] || exit 1 # only two args allowed
[[ $1 =~ ^[0-9]+$ ]] || exit 1 # first arg must be numeric
pdir="/proc/$1"
owner=$(stat --printf '%U' "$pdir") # GNU stat's printf
[ "$owner" = "$SUDO_USER" ]] || exit 1 # owner must match
find "$pdir/fd/" -lname "$2" -printf '%l\0'
如果您想变得更奇特,您可以针对不同的错误条件使用不同的退出代码(考虑到find
如果运行的话也将有自己的退出代码)。
答案2
一句与证据配合的俏皮话,所以应该值得与扎图拉一起使用:
lsof 2> /dev/null | grep evince | grep pdf$ | awk '{print $NF}' | uniq
/home/ron/165_dollar_checks.pdf
/home/ron/12_mnt_exh_05_box.pdf