Como uso o Ruby para scripts de shell?


165

Eu tenho algumas tarefas simples de script de shell que eu quero fazer

Por exemplo: Selecionando um arquivo no diretório ativo de uma lista dos arquivos que correspondem a alguma expressão regular.

Eu sei que posso fazer esse tipo de coisa usando bash e grep padrão, mas seria bom poder hackear scripts rápidos que funcionem no Windows e Linux sem que eu tenha que memorizar uma pilha de programas de linha de comando e sinalizadores etc.

Tentei fazer isso, mas acabei ficando confuso sobre onde deveria obter informações, como uma referência ao diretório atual.

Portanto, a questão é quais partes das bibliotecas Ruby eu preciso saber para escrever scripts shell ruby?


3
Provavelmente não é uma boa resposta, mas o Ruby Prático para Administração de Sistemas é uma ótima referência. amazon.com/Practical-System-Administration-Experts-Source/dp/…
exiquio

Respostas:


148

Por padrão, você já tem acesso ao Dir e ao arquivo , que são bastante úteis por si só.

Dir['*.rb'] #basic globs
Dir['**/*.rb'] #** == any depth of directory, including current dir.
#=> array of relative names

File.expand_path('~/file.txt') #=> "/User/mat/file.txt"
File.dirname('dir/file.txt') #=> 'dir'
File.basename('dir/file.txt') #=> 'file.txt'
File.join('a', 'bunch', 'of', 'strings') #=> 'a/bunch/of/strings'

__FILE__ #=> the name of the current file

Também útil no stdlib é o FileUtils

require 'fileutils' #I know, no underscore is not ruby-like
include FileUtils
# Gives you access (without prepending by 'FileUtils.') to
cd(dir, options)
cd(dir, options) {|dir| .... }
pwd()
mkdir(dir, options)
mkdir(list, options)
mkdir_p(dir, options)
mkdir_p(list, options)
rmdir(dir, options)
rmdir(list, options)
ln(old, new, options)
ln(list, destdir, options)
ln_s(old, new, options)
ln_s(list, destdir, options)
ln_sf(src, dest, options)
cp(src, dest, options)
cp(list, dir, options)
cp_r(src, dest, options)
cp_r(list, dir, options)
mv(src, dest, options)
mv(list, dir, options)
rm(list, options)
rm_r(list, options)
rm_rf(list, options)
install(src, dest, mode = <src's>, options)
chmod(mode, list, options)
chmod_R(mode, list, options)
chown(user, group, list, options)
chown_R(user, group, list, options)
touch(list, options)

O que é bem legal


110

Como os outros já disseram, sua primeira linha deve ser

#!/usr/bin/env ruby

E você também precisa torná-lo executável: (no shell)

chmod +x test.rb

Depois segue o código ruby. Se você abrir um arquivo

File.open("file", "r") do |io|
    # do something with io
end

o arquivo é aberto no diretório atual que você obteria pwdno shell.

O caminho para o seu script também é simples de obter. Com $0você, obtém o primeiro argumento do shell, que é o caminho relativo para o seu script. O caminho absoluto pode ser determinado assim:

#!/usr/bin/env ruby
require 'pathname'
p Pathname.new($0).realpath()

Para operações do sistema de arquivos, quase sempre uso o Pathname. Este é um invólucro para muitas das outras classes relacionadas ao sistema de arquivos. Também é útil: Dir, File ...


66

Aqui está algo importante que está faltando nas outras respostas: os parâmetros da linha de comando são expostos ao seu script de shell Ruby por meio da matriz ARGV (global).

Portanto, se você tivesse um script chamado my_shell_script:

#!/usr/bin/env ruby
puts "I was passed: "
ARGV.each do |value|
  puts value
end

... torná-lo executável (como outros já mencionaram):

chmod u+x my_shell_script

E chame assim:

> ./my_shell_script one two three four five

Você obteria isso:

I was passed: 
one
two
three
four
five

Os argumentos funcionam bem com a expansão do nome do arquivo:

./my_shell_script *

I was passed: 
a_file_in_the_current_directory
another_file    
my_shell_script
the_last_file

A maior parte disso funciona apenas no UNIX (Linux, Mac OS X), mas você pode fazer coisas semelhantes (embora menos convenientes) no Windows.


32

Há muitos bons conselhos aqui, então eu queria adicionar um pouquinho mais.

  1. Os backticks (ou back-ticks) permitem fazer algumas coisas de script muito mais facilmente. Considerar

    puts `find . | grep -i lib`
  2. Se você tiver problemas para obter a saída dos backticks, o problema será o erro padrão, em vez de sair do padrão. Use este conselho

    out = `git status 2>&1`
  3. Os backticks fazem interpolação de string:

    blah = 'lib'
    `touch #{blah}`
  4. Você também pode entrar no Ruby . É um link para o meu blog, mas tem um link aqui, então está tudo bem :) Provavelmente existem coisas mais avançadas por aí sobre este tópico.

  5. Como outras pessoas notaram, se você quer levar a sério, existe o Rush: não apenas como um substituto do shell (o que é um pouco doido demais para mim), mas também como uma biblioteca para seu uso em scripts e programas do shell.


No Mac, use Applescript dentro do Ruby para obter mais poder. Aqui está o meu shell_herescript:

#!/usr/bin/env ruby
`env | pbcopy` 
cmd =  %Q@tell app "Terminal" to do script "$(paste_env)"@
puts cmd

`osascript -e "${cmd}"`

Eu apenas tive que recuar o código mais 4 espaços para que eles fossem formatados. Também retiro os backticks, mas não conheço muito bem o Ruby, então você deve verificar se é o que pretendia.
Bill o Lagarto

@ Bill the Lizard, sim, esse era o 'truque' que eu estava precisando: os dois travessões. OBRIGADO PELA AJUDA.
Dan Rosenstark 6/03/10


22

Compre uma cópia do Everyday Scripting with Ruby . Tem muitas dicas úteis sobre como fazer os tipos de coisas que você deseja fazer.


2
Bom livro, estou lendo agora: parece uma jornada de código zen. E se você não conhece o TDD, aprenderá o básico do TDD por todo o caminho.
Sébastien RoccaSerra

Eu acho que o livro tem algumas informações boas, mas muito caras para programadores experientes.
OD mesclou


12

digamos que você escreva seu script.rbscript. colocar:

#!/usr/bin/env ruby

como a primeira linha e faça um chmod +x script.rb


7

Quando você deseja escrever scripts ruby ​​mais complexos, essas ferramentas podem ajudar:

Por exemplo:

  • thor (uma estrutura de script)

  • gli (interface semelhante ao git)

  • metadona (para criar ferramentas simples)

Eles dão a você um começo rápido para escrever seus próprios scripts, especialmente o 'aplicativo de linha de comando'.


5

A resposta acima é interessante e muito útil ao usar Ruby como shell script. Para mim, eu não uso Ruby como minha linguagem diária e prefiro usar ruby ​​apenas como controle de fluxo e ainda usar o bash para executar as tarefas.

Alguma função auxiliar pode ser usada para testar o resultado da execução

#!/usr/bin/env ruby
module ShellHelper
  def test(command)
    `#{command} 2> /dev/null`
    $?.success?
  end

  def execute(command, raise_on_error = true)
    result = `#{command}`
    raise "execute command failed\n" if (not $?.success?) and raise_on_error
    return $?.success?
  end

  def print_exit(message)
    print "#{message}\n"
    exit
  end

  module_function :execute, :print_exit, :test
end

Com o helper, o script ruby ​​pode ser semelhante ao bash:

#!/usr/bin/env ruby
require './shell_helper'
include ShellHelper

print_exit "config already exists" if test "ls config"

things.each do |thing|
  next if not test "ls #{thing}/config"
  execute "cp -fr #{thing}/config_template config/#{thing}"
end

Cara, isso é ótimo, obrigado!
Victor Martins

4

"Como eu escrevo ruby" está um pouco além do escopo do SO.

Mas, para transformar esses scripts ruby ​​em scripts executáveis, coloque isso como a primeira linha do seu script ruby:

#!/path/to/ruby

Em seguida, torne o arquivo executável:

chmod a+x myscript.rb

e você vai embora.


4

Coloque isso no início do seu script.rb

#!/usr/bin/env ruby

Em seguida, marque-o como executável:

chmod +x script.rb

3

A resposta do webmat é perfeita. Eu só quero te indicar uma adição. Se você precisar lidar muito com os parâmetros da linha de comando para seus scripts, use optparse . É simples e ajuda tremendamente.


3

Em ruby, a constante __FILE__sempre fornecerá o caminho do script que você está executando.

No Linux, /usr/bin/envé seu amigo:

#! /usr/bin/env ruby
# Extension of this script does not matter as long
# as it is executable (chmod +x)
puts File.expand_path(__FILE__)

No Windows, depende se os arquivos .rb estão ou não associados ao ruby. Se eles são:

# This script filename must end with .rb
puts File.expand_path(__FILE__)

Se não estiverem, você precisará chamar explicitamente o ruby, eu uso um arquivo .cmd intermediário:

my_script.cmd:

@ruby %~dp0\my_script.rb

my_script.rb:

puts File.expand_path(__FILE__)
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.