我如何以编程方式确定 evince 中当前打开了哪些文件?

我如何以编程方式确定 evince 中当前打开了哪些文件?

我使用 GUI 中的文档查看器打开了一个 PDF 文件。有没有办法在终端/脚本中获取此文件的路径?

答案1

总结:

for ip in $(pgrep -x evince); do lsof -F +p $ip|grep -i '^n.*\.pdf$'|sed s/^n//g; done

解释:

Document Viewer是程序的友好名称/usr/bin/evince。因此,首先我们需要找到进程 ID (PID) evince

$ pgrep -x evince
22291

要列出此 PID 打开的所有文件,我们将使用该lsof命令(请注意,如果我们运行多个 evince 实例,我们需要对每个 PID 重复此操作)

$ lsof -F +p 22291
some other files opened
.
.
.
n/home/c0rp/File.pdf

接下来我们将仅对 pdf 进行 grep 并丢弃行首不相关的 n:

$ lsof -Fn +p 22291 | grep -i '^n.*\.pdf$' | sed s/^n//g
/home/c0rp/File.pdf

最后将所有内容合并到一个 bash 行中:

for ip in $(pgrep -x evince); do lsof -F +p $ip|grep -i '^n.*\.pdf$'|sed s/^n//g; done

这句话的灵感来自于 terdon 的答案,它解决同一问题的方式也非常有趣。


如果你对什么感兴趣n为了,这里是关于该选项的lsof -Fn引述:man lsof-F

OUTPUT FOR OTHER PROGRAMS
       When the -F option is specified, lsof produces output that is  suitable
       for  processing by another program - e.g, an awk or Perl script, or a C
       program. 
...
...
       These  are  the  fields  that  lsof will produce.  The single character
       listed first is the field identifier.
...
...
            n    file name, comment, Internet address
...
...

所以-Fn,说给我看看file name, comment, Internet address

答案2

另一种方法是

$ for ip in $(pgrep -x evince); do lsof -F +p $ip  | grep -oP '^n\K.*\.pdf$'; done
/home/terdon/file1.pdf
/home/terdon/file2.pdf

解释

一般来说,每当你想要搜索一个进程时,pgrep比 更好,ps -ef | grep process因为后者也会匹配grep进程本身。例如:

$ ps -ef | grep emacs
terdon    6647  6424 23 16:26 pts/14   00:00:02 emacs
terdon    6813  6424  0 16:26 pts/14   00:00:00 grep --color emacs
$ pgrep emacs
6647

-x选项仅返回其整个名称与传递的字符串匹配的进程。这是必需的,因为evince还会启动守护进程(evinced),并且也将在没有-x-l是打印名称以及 PID)的情况下进行匹配:

$ pgrep -l evince
4606 evince
4611 evinced
4613 evince
$ pgrep -lx evince
4606 evince
4613 evince

因此,for 循环将lsof在 返回的每个 PID 上运行pgrep。然后将它们传递给grep。该-o选项表示“仅打印行的匹配部分”,并且-P激活 Perl 兼容正则表达式,这让我们可以使用\K。在 PCRE 中,\K表示“丢弃\K ". In other words, since I am using-o , it will match lines beginning withn and ending with.pdf but it will not print the matchedn 之前匹配的所有内容”。结果是只打印文件的名称。

答案3

您甚至不需要指定通过文档查看器打开的 pdf 的文件名。下面的命令将显示通过文档查看器打开的所有 pdf 文件的路径。evince是通过终端打开文档查看器的实际命令。

ps -ef | grep evince | sed -n '/.*\.pdf/p' | sed 's/.*evince \(.*\)$/\1/g'

例子:

$ ps -ef | grep evince | sed -n '/.*\.pdf/p' | sed 's/.*evince \(.*\)$/\1/g'
/media/avinash/C68C57908C5779BF/pdf/PHP/PHP-Manual.pdf
/media/avinash/C68C57908C5779BF/pdf/python.pdf

但所有的功劳都归功于@Corp

相关内容