Como posso determinar programaticamente quais arquivos estão atualmente abertos no evince?

6

Eu abri um arquivo PDF com o visualizador de documentos da GUI. Existe alguma maneira de obter o caminho deste arquivo em um terminal / script?

    
por Mohammad Reza Rezwani 11.05.2014 / 07:14

3 respostas

12
TLDR:

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

Explicação:

Document Viewer é o nome amigável do programa /usr/bin/evince . Então, primeiro precisamos encontrar o ID do processo (PID) de evince :

$ pgrep -x evince
22291

Para listar todos os arquivos abertos por este PID, usaremos o comando lsof (note que precisaremos repetir isso para cada PID, caso tenhamos mais de uma instância do evince em execução)

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

Em seguida, vamos apenas para os pdfs e descartar o n irrelevante no início da linha:

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

Finalmente, para combinar tudo em uma linha bash:

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

Este one-liner foi inspirado na resposta de Terdon, que também é muito interessante na maneira como resolve o mesmo problema.

Se você estiver interessado no que n em lsof -Fn , aqui estão as citações de man lsof sobre a opção -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
...
...

então -Fn , está dizendo: mostre-me file name, comment, Internet address

    
por c0rp 26.12.2014 / 18:05
5

Outra abordagem seria algo como

$ 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

Explicação

Em geral, sempre que você quiser pesquisar um processo, pgrep é melhor que ps -ef | grep process , pois o último também corresponderá ao processo grep em si. Por exemplo:

$ 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

A opção -x retorna apenas processos cujo nome inteiro corresponde à sequência passada. Isso é necessário porque evince também inicia um daemon ( evinced ) e que também será correspondido sem o -x (o -l é para imprimir o nome, assim como o PID):

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

Portanto, o loop for executará lsof em cada um dos PIDs retornados por pgrep . Estes são então passados através de grep . A opção -o significa "imprimir apenas a parte correspondente da linha" e o -P ativa Perl Compatible Regular Expressions, o que nos permite usar \K . Nos PCREs, \K significa "descartar tudo correspondido antes do \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 '. O resultado é que apenas o nome do arquivo é impresso.

    
por terdon 11.05.2014 / 16:32
2

Você não precisa especificar nem mesmo o nome do arquivo do pdf aberto através do Document Viewer. Este comando abaixo exibirá os caminhos de todos os arquivos pdf abertos através do Visualizador de Documentos. evince é o comando real para abrir o Visualizador de Documentos via terminal.

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

Exemplo:

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

Mas todo o crédito vai para @Corp .

    
por Avinash Raj 11.05.2014 / 09:28