Come posso usare Ruby per gli script di shell?


165

Ho alcune semplici attività di scripting della shell che voglio fare

Ad esempio: selezione di un file nella directory di lavoro da un elenco di file corrispondenti a espressioni regolari.

So che posso fare questo genere di cose usando bash e grep standard ma sarei bello essere in grado di hackerare script veloci che funzioneranno in Windows e Linux senza che io debba memorizzare un mucchio di programmi da riga di comando e flag, ecc.

Ho provato a farlo funzionare, ma alla fine mi sono confuso su dove avrei dovuto ottenere informazioni come un riferimento alla directory corrente

Quindi la domanda è: quali parti delle librerie Ruby devo sapere per scrivere script di ruby ​​shell?


3
Probabilmente non è una buona risposta, ma Practy Ruby for System Administration è un ottimo riferimento. amazon.com/Practical-System-Administration-Experts-Source/dp/…
exiquio

Risposte:


148

Per impostazione predefinita, hai già accesso a Dir e File , che sono abbastanza utili da soli.

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

Utile anche dallo stdlib è 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)

È molto carino


110

Come hanno già detto gli altri, la tua prima linea dovrebbe essere

#!/usr/bin/env ruby

E devi anche renderlo eseguibile: (nella shell)

chmod +x test.rb

Quindi segue il codice rubino. Se apri un file

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

il file viene aperto nella directory corrente che otterresti pwdnella shell.

Anche il percorso del tuo script è semplice da ottenere. Con $0te ottieni il primo argomento della shell, che è il percorso relativo al tuo script. Il percorso assoluto può essere determinato in questo modo:

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

Per le operazioni del file system uso quasi sempre Pathname. Questo è un wrapper per molte altre classi correlate al file system. Utile anche: Dir, File ...


66

Ecco qualcosa di importante che manca alle altre risposte: i parametri della riga di comando sono esposti allo script della shell Ruby attraverso l'array ARGV (globale).

Quindi, se avessi uno script chiamato my_shell_script:

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

... renderlo eseguibile (come altri hanno già detto):

chmod u+x my_shell_script

E chiamalo così:

> ./my_shell_script one two three four five

Otterresti questo:

I was passed: 
one
two
three
four
five

Gli argomenti funzionano bene con l'espansione del nome file:

./my_shell_script *

I was passed: 
a_file_in_the_current_directory
another_file    
my_shell_script
the_last_file

La maggior parte di questi funziona solo su UNIX (Linux, Mac OS X), ma puoi fare cose simili (anche se meno convenienti) in Windows.


32

Ci sono molti buoni consigli qui, quindi volevo aggiungere un po 'di più.

  1. I backtick (o back-tick) ti consentono di eseguire alcune operazioni di scripting molto più facilmente. Tener conto di

    puts `find . | grep -i lib`
  2. Se riscontri problemi nell'ottenere l'output dei backtick, le cose andranno allo standard err invece che allo standard out. Usa questo consiglio

    out = `git status 2>&1`
  3. I backtick eseguono l'interpolazione di stringhe:

    blah = 'lib'
    `touch #{blah}`
  4. Puoi anche fare pipa dentro Ruby . È un link al mio blog, ma si collega qui quindi va bene :) Probabilmente ci sono cose più avanzate là fuori su questo argomento.

  5. Come altri hanno notato, se vuoi fare sul serio c'è Rush: non solo come una sostituzione della shell (che è un po 'troppo bizzarra per me) ma anche come una libreria per il tuo uso negli script e nei programmi della shell.


Su Mac, usa Applescript in Ruby per avere più potenza. Ecco la mia shell_heresceneggiatura:

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

`osascript -e "${cmd}"`

Ho dovuto solo indentare il codice di altri 4 spazi per poterli formattare. Ho anche rimesso i backtick, ma non conosco molto bene Ruby, quindi ti consigliamo di verificare che sia quello che volevi.
Bill the Lizard,

@Bill the Lizard, sì, quello era il "trucco" di cui avevo bisogno: i doppi rientri. GRAZIE PER L'AIUTO.
Dan Rosenstark,


22

Vai a procurarti una copia di Everyday Scripting con Ruby . Ha molti consigli utili su come fare i tipi di cose che vuoi fare.


2
Buon libro, lo sto leggendo proprio ora: sembra un viaggio in codice zen. E se non conosci il TDD, imparerai le basi del TDD lungo la strada.
Sébastien RoccaSerra,

Penso che il libro abbia delle buone informazioni ma un sovraccarico per programmatori esperti.
La D si unì l'


12

diciamo che scrivi la tua script.rbsceneggiatura. mettere:

#!/usr/bin/env ruby

come prima riga e fare un chmod +x script.rb


7

Quando si desidera scrivere script ruby ​​più complessi, questi strumenti possono aiutare:

Per esempio:

  • thor (un framework di scripting)

  • gli (interfaccia git like)

  • metadone (per la creazione di strumenti semplici)

Ti danno un rapido avvio per scrivere i tuoi script, in particolare 'app a riga di comando'.


5

La risposta sopra è interessante e molto utile quando si usa Ruby come script di shell. Per quanto mi riguarda, non uso Ruby come linguaggio quotidiano e preferisco usare Ruby solo come controllo del flusso e utilizzo ancora bash per eseguire le attività.

Alcune funzioni di supporto possono essere utilizzate per testare il risultato dell'esecuzione

#!/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

Con l'helper, la sceneggiatura ruby ​​potrebbe essere allo stesso modo 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

Amico, è fantastico, grazie!
Victor Martins,

4

"Come faccio a scrivere ruby" è un po 'oltre lo scopo di SO.

Ma per trasformare questi script ruby ​​in script eseguibili, inseriscilo come prima riga del tuo script ruby:

#!/path/to/ruby

Quindi rendere eseguibile il file:

chmod a+x myscript.rb

e vai via.


4

Posizionalo all'inizio di script.rb

#!/usr/bin/env ruby

Quindi contrassegnalo come eseguibile:

chmod +x script.rb

3

La risposta di webmat è perfetta. Voglio solo indicarti un'aggiunta. Se devi gestire molto i parametri della riga di comando per i tuoi script, dovresti usare optparse . È semplice e ti aiuta moltissimo.


3

In rubino, la costante __FILE__ ti darà sempre il percorso dello script che stai eseguendo.

Su Linux, /usr/bin/envè tuo amico:

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

Su Windows dipende se i file .rb sono associati o meno a ruby. Se sono:

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

Se non lo sono, devi invocare esplicitamente ruby ​​su di loro, io uso un file intermedio .cmd:

my_script.cmd:

@ruby %~dp0\my_script.rb

my_script.rb:

puts File.expand_path(__FILE__)
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.