如何以编程方式确定当前在 evince 中打开的文件?

Moh*_*ani 6 command-line evince

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

c0r*_*0rp 12

域名注册地址:

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

解释:

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

$ pgrep -x evince
22291
Run Code Online (Sandbox Code Playgroud)

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

$ lsof -F +p 22291
some other files opened
.
.
.
n/home/c0rp/File.pdf
Run Code Online (Sandbox Code Playgroud)

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

$ lsof -Fn +p 22291 | grep -i '^n.*\.pdf$' | sed s/^n//g
/home/c0rp/File.pdf
Run Code Online (Sandbox Code Playgroud)

最后将所有内容组合在一个 bash 行中:

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

这个 one-liner 的灵感来自 terdon 的答案,它在解决同一问题的方式上也非常有趣。


如果您对n inlsof -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
...
...
Run Code Online (Sandbox Code Playgroud)

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


ter*_*don 5

另一种方法是这样的

$ 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
Run Code Online (Sandbox Code Playgroud)

解释

一般来说,无论何时你想搜索一个进程,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
Run Code Online (Sandbox Code Playgroud)

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

$ pgrep -l evince
4606 evince
4611 evinced
4613 evince
$ pgrep -lx evince
4606 evince
4613 evince
Run Code Online (Sandbox Code Playgroud)

因此,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`之前匹配的所有内容。结果是只打印文件名。