Comment utiliser Ruby pour les scripts shell?

J'ai quelques tâches de script shell simples que je veux faire

Par exemple: sélection d'un fichier dans le répertoire de travail à partir d'une liste de fichiers correspondant à une expression régulière.

Je sais que je peux faire ce genre de chose en utilisant Bash standard et grep mais je serais bien de pouvoir pirater des scripts rapides qui fonctionneront sous windows et linux sans que je doive mémoriser un tas de programmes et de drapeaux en ligne de commande, etc.

J'ai essayé de faire avancer ça mais j'ai fini par devenir confus sur l'endroit où je devrais obtenir des informations telles qu'une référence au répertoire courant

La question est donc de savoir quelles parties des bibliothèques Ruby dois-je savoir pour écrire des scripts shell ruby?

159
demandé sur ergosys 2008-10-03 15:03:06

13 réponses

Par défaut, vous avez déjà accès à Dir et Fichier, qui sont assez utiles par eux-mêmes.

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

Aussi utile à partir de la stdlib est 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)

Ce qui est plutôt sympa

141
répondu webmat 2008-10-03 13:30:59

, Comme les autres l'ont déjà dit, votre première ligne devrait être

#!/usr/bin/env ruby

Et vous devez également le rendre exécutable: (dans le shell)

chmod +x test.rb

Suit ensuite le code ruby. Si vous ouvrez un fichier

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

Le fichier est ouvert dans le répertoire courant, vous obtiendriez avec pwd dans le shell.

Le chemin d'accès à votre script est également simple à obtenir. Avec $0 vous obtenez le premier argument du shell, qui est le chemin relatif à votre script. Le chemin absolu peut être déterminé comme que:

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

Pour les opérations du système de fichiers, j'utilise presque toujours Pathname. Ceci est un wrapper pour beaucoup d'autres classes liées au système de fichiers. Aussi utile: Dir, fichier...

108
répondu Georg Schölly 2008-10-03 13:25:48

Voici quelque chose d'important qui manque dans les autres réponses: les paramètres de ligne de commande sont exposés à votre script shell Ruby via le tableau ARGV (global).

Donc, si vous aviez un script appelé my_shell_script:

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

...le rendre exécutable (comme d'autres l'ont mentionné):

chmod u+x my_shell_script

Et appelez-le comme ceci:

> ./my_shell_script one two three four five

, Vous obtiendrez ceci:

I was passed: 
one
two
three
four
five

Les arguments fonctionnent bien avec l'expansion du nom de fichier:

./my_shell_script *

I was passed: 
a_file_in_the_current_directory
another_file    
my_shell_script
the_last_file

La Plupart de cela ne fonctionne que sur UNIX (Linux, Mac OS X), mais vous pouvez faire des choses similaires (bien que moins pratiques) dans Windows.

66
répondu Craig Walker 2009-11-27 05:52:03

Il y a beaucoup de bons conseils ici, donc je voulais en ajouter un tout petit peu plus.

  1. Les Backticks (ou back-ticks) vous permettent de faire des scripts beaucoup plus facilement. Considérer

    puts `find . | grep -i lib`
    
  2. Si vous rencontrez des problèmes avec l'obtention de la sortie des backticks, les choses vont se tromper standard au lieu de standard out. utilisez ce conseil

    out = `git status 2>&1`
    
  3. Les Backticks font une interpolation de chaîne:

    blah = 'lib'
    `touch #{blah}`
    
  4. Vous pouvez tuyau à l'intérieur Ruby, trop. C'est un lien vers mon blog, mais il renvoie ici donc c'est bon :) il y a probablement des choses plus avancées sur ce sujet.

  5. Comme d'autres personnes l'ont noté, si vous voulez être sérieux, il y a Rush: pas seulement comme un remplacement de shell (ce qui est un peu trop loufoque pour moi) mais aussi comme une bibliothèque pour votre utilisation dans les scripts et programmes shell.


Sur Mac, utilisez Applescript dans Ruby pour plus de puissance. Voici mon script shell_here:

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

`osascript -e "${cmd}"`
31
répondu Dan Rosenstark 2017-12-27 20:41:48

Allez vous procurer une copie de Scripts quotidiens avec Ruby . Il a beaucoup de conseils utiles sur la façon de faire les types de choses que vous voulez faire.

21
répondu Aaron Hinni 2008-10-03 12:42:06

Cela peut également être utile: http://rush.heroku.com/

Je ne l'ai pas beaucoup utilisé, mais ça a l'air plutôt cool

Du site:

Rush est un remplacement pour le shell unix (bash, zsh, etc) qui utilise la syntaxe Ruby pure. Grep à travers les fichiers, trouver et tuer les processus, copier des fichiers-Tout ce que vous faites dans le shell, maintenant dans Ruby

12
répondu craigp 2008-10-05 09:29:29

Disons que vous écrivez votre script script.rb. mettre:

#!/usr/bin/env ruby

Comme première ligne et faites un chmod +x script.rb

10
répondu Vasil 2016-04-20 06:52:35

Lorsque vous voulez écrire des scripts ruby plus complexes, ces outils peuvent vous aider:

Par exemple:

  • Thor(un framework de scripts)

  • Gli (interface de type git)

  • Méthadone (pour créer des outils simples)

Ils vous donnent un démarrage rapide pour écrire vos propres scripts, en particulier'application de ligne de commande'.

6
répondu Bohr 2013-03-19 07:59:46

"Comment écrire ruby" est un peu au-delà de la portée de SO.

Mais pour transformer ces scripts ruby en scripts exécutables, mettez ceci comme première ligne de votre script ruby:

#!/path/to/ruby

Ensuite, rendez le fichier exécutable:

chmod a+x myscript.rb

Et vous partez.

4
répondu Matthew Scharley 2008-10-03 11:07:18

Placez ceci au début de votre script.rb

#!/usr/bin/env ruby

Puis marquez-le comme exécutable:

chmod +x script.rb
4
répondu Daniel Beardsley 2008-10-03 11:37:45

La réponse de webmat est parfaite. Je veux juste vous montrer un plus. Si vous avez beaucoup avec les paramètres de ligne de commande pour vos scripts, vous devez utiliser optparse. Il est simple et vous aide énormément.

3
répondu awenkhh 2017-05-23 12:02:21

Dans ruby, la constante __FILE__ vous donnera toujours le chemin du script que vous exécutez.

Sous Linux, /usr/bin/env est votre ami:

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

Sous Windows, Cela dépend si oui ou non .les fichiers rb sont associés avec ruby. Si elles sont:

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

S'ils ne le sont pas, vous devez invoquer explicitement ruby sur eux, j'utilise un intermédiaire .fichier cmd:

My_script.cmd:

@ruby %~dp0\my_script.rb

My_script.rb:

puts File.expand_path(__FILE__)
3
répondu bltxd 2016-04-20 06:53:07

La réponse ci-dessus est intéressante et très utile lors de l'utilisation de Ruby comme script shell. Pour moi, je n'utilise pas Ruby comme langage quotidien et je préfère utiliser ruby comme contrôle de flux uniquement et utiliser toujours bash pour faire les tâches.

Une fonction d'aide peut être utilisée pour tester le résultat de l'exécution

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

Avec l'aide, le script ruby pourrait être bash comme:

#!/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
3
répondu Houcheng 2016-12-01 17:10:47