我使用 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 with
n and ending with
.pdf but it will not print the matched
n 之前匹配的所有内容”。结果是只打印文件的名称。
答案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。