freak’s blog

Interessantices

Enviado em Linux, Programação by Henrique C. Alves em Abril 17th, 2008

Depois de longo tempo sem postar, eis que eu lembro que tenho um blog novamente. ;) É que na verdade o plano era mudar o blog para outro servidor (junto do meu portfolio e um csv pra que eu possa subir alguns códigos interessantes), mas ainda não tive tempo.

No entanto, hoje eu tenho algo interessante pra postar, então lá vai. Eu costumo frequentar o fórum internacional do Arch, e nesse tópico um usuário deu uma idéia interessante: como seria possível copiar um arquivo entre TERMINAIS. Ou seja, você tem 2 terminais abertos (ou mais), e quer copiar um arquivo de um terminal para o diretório que está sendo usado no outro. Obviamente, você usaria algo como:

$ cp arquivo o-caminho-completo-de-onde-está-o outro-terminal

Mas isso é chato. Então eu pensei, que bom seria se eu pudesse simplesmente fazer:

$ cp arquivo /dev/pts/1

E a cópia iria para o diretorio em que o pts/1 está trabalhando. Bem, o comando cp não sabe funcionar assim. Mas ele também não sabe que eu fui treinado pelo MacGyver. Então, vejamos como implementar esse recurso usando minha linguagem preferida, Ruby (não confundir com Rails, POR FAVOR!):

#!/usr/bin/ruby

if (ARGV.empty?) || (ARGV[0] == "-h") || (ARGV.size < 2)
  STDERR.puts <<EOS
Usage: #{$0} [-h] FILE TARGET

If TARGET is a terminal device (under /dev/), the copy operation will occur
to the terminal's current working dir. Otherwise, will behave like as a path.

EOS
  exit 1
end

file   = ARGV[0].to_s.strip
target = ARGV[1].to_s.strip

if File.directory? target
  path = target
else
  unless (pts = target.split("/dev/")[1])
    STDERR.puts "Invalid target: #{target}"
    exit 1
  end
  if (pid = `pgrep -n -t #{pts}`).empty?
    STDERR.puts "Cannot determine pwd of device: #{pts}"
    exit 1
  end
  path = `pwdx #{pid}`.split(": ")[1].strip
  unless File.directory? path
    STDERR.puts path
    exit 1
  end
end

`cp #{file} #{path}`

Esse script irá permitir copiar um arquivo apontando como alvo um terminal ao invés de um caminho, e vai se encarregar de encontrar o diretório atualmente usado. Se o terminal tem mais de uma shell aninhada (ou seja, se você abriu o terminal, e está rodando mais um shell dentro), ele irá usar o diretório do último shell chamado. Se ao invés de apontar um terminal, apontar um caminho, ele irá se comportar igual ao cp comum.

Minha sugestão de uso é copiar para /usr/local/bin/cpt e criar um alias no .bashrc:

alias cp='/usr/local/bin/cpt'

Outra sugestão também é colocar no .bashrc:

if [ "$DISPLAY" ]; then
echo -n -e “\e]0;`tty`\a”
fi

Com isso, todos os terminais terão como título o seu pts, assim fica fácil ver qual janela ou aba de terminal você quer destinar a cópia (só vai executar se for uma janela de terminal no Xorg, não no terminal em modo texto).

Por fim, você irá usar o comando, por exemplo:

$ cp arquivinho.txt /dev/pts/2

E bingo, seu arquivo vai estar disponível no seu outro terminal aberto, sem ter que quebrar a cabeça pra achar o caminho completo. Pra quem usa vários terminais abertos (eu), ou usa tilling window managers (xmonad, awesome), fica bem mais prático trabalhar.

Atenção: não sei como o script se comporta em shells não-Bash (zsh, csh), apesar de que no dash deve funcionar corretamente.

Apesar de nada ortodoxo (afinal, pela lógica do UNIX, copiar um arquivo para um device não faz sentido), o recurso é prático. Boa diversão!

One Response to 'Interessantices'

Subscribe to comments with RSS or TrackBack to 'Interessantices'.

  1. Allan said, on Maio 1st, 2008 at 10:25 am

    Legal Henrique… eu realmente to precisando aprender um pouco de shell script =p… tentou fazer isso com PHP?

    Abraço

Leave a Reply