Як використовувати Ruby для сценаріїв оболонок?


165

У мене є кілька простих сценаріїв оболонок, які я хочу зробити

Наприклад: Вибір файлу в робочому каталозі зі списку файлів, що відповідають деяким регулярним виразам.

Я знаю, що я можу робити таку річ, використовуючи стандартні bash та grep, але мені було б непогано мати змогу зламати швидкі сценарії, які працюватимуть у Windows та Linux, без мене запам'ятовувати купу програм та прапорів командного рядка тощо.

Я намагався це зробити, але в результаті розгубився, де мені слід отримати інформацію, наприклад, посилання на поточний каталог

Отже, питання полягає в тому, які частини бібліотек Ruby мені потрібно знати, щоб писати сценарії рубінової оболонки?


3
Напевно, це не гарна відповідь, але практичний Ruby для системного адміністрування є чудовим посиланням. amazon.com/Practical-System-Administration-Experts-Source/dp/…
exiquio

Відповіді:


148

За замовчуванням у вас уже є доступ до Dir та File , які самі корисні.

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

Також корисним від 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)

Що досить приємно


110

Як уже говорили інші, ваш перший рядок повинен бути

#!/usr/bin/env ruby

І ви також повинні зробити його виконуваним: (в оболонці)

chmod +x test.rb

Далі слід рубіновий код. Якщо ви відкриєте файл

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

файл відкривається в поточному каталозі, який ви отримаєте pwdв оболонці.

Шлях до вашого сценарію також простий. З $0вами ви отримуєте перший аргумент оболонки, який є відносним шляхом до вашого сценарію. Абсолютний шлях можна визначити так:

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

Для операцій з файловою системою я майже завжди використовую Pathname. Це обгортка для багатьох інших класів, пов'язаних з файловою системою. Також корисно: Dir, файл ...


66

Ось щось важливе, чого не вистачає в інших відповідях: параметри командного рядка піддаються дії сценарію оболонки Ruby через масив ARGV (глобальний).

Отже, якщо у вас був сценарій під назвою my_shell_script:

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

... зробіть його виконуваним (як уже згадували інші):

chmod u+x my_shell_script

І називайте це так:

> ./my_shell_script one two three four five

Ви отримаєте це:

I was passed: 
one
two
three
four
five

Аргументи чудово працюють з розширенням імені файлів:

./my_shell_script *

I was passed: 
a_file_in_the_current_directory
another_file    
my_shell_script
the_last_file

Більшість цього працює лише в UNIX (Linux, Mac OS X), але ви можете робити подібні (хоча і менш зручні) речі в Windows.


32

Тут є багато хороших порад, тому я хотів додати ще трохи.

  1. Зворотні посилання (або зворотні кліщі) дозволяють вам робити деякі сценарії набагато простіше. Розглянемо

    puts `find . | grep -i lib`
  2. Якщо у вас виникли проблеми з отриманням вихідних задників, цей матеріал стане стандартним помилкою, а не стандартним. Скористайтеся цією порадою

    out = `git status 2>&1`
  3. Повернення робить інтерполяцію рядків:

    blah = 'lib'
    `touch #{blah}`
  4. Ви також можете трубу всередині Ruby . Це посилання на мій блог, але воно посилається тут, так що це нормально :) На цю тему, мабуть, є більш досконалі речі.

  5. Як зазначали інші люди, якщо ви хочете серйозно зайнятися, є Rush: не тільки як заміна оболонки (що для мене трохи занадто задумливо), але і як бібліотека для використання в скриптах і програмах оболонок.


На Mac використовуйте Applescript всередині Ruby для отримання більшої потужності. Ось мій shell_hereсценарій:

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

`osascript -e "${cmd}"`

Мені просто довелося відрізати код ще 4 пробілами для їх форматування. Я також ставив задню панель назад, але я не знаю Рубі зовсім добре, тому ви хочете перевірити, щоб переконатися, що це те, що ви задумали.
Білл Ящірка

@Bill Ящірка, так, це був той "трюк", який мені знадобився: подвійні відступи. ДЯКУЮ ЗА ДОПОМОГУ.
Дан Розенстарк

1

22

Іди собі копію щоденного сценарію з Рубі . У ньому є багато корисних порад щодо того, як робити типи речей, які ти хочеш зробити.


2
Хороша книга, я зараз її читаю: це відчуття подорожі в дзен-коді. І якщо ви не знаєте TDD, ви дізнаєтесь основи TDD ще довше.
Sébastien RoccaSerra

Я думаю, що в книзі є хороша інформація, але набагато накладніші для досвідчених програмістів.
D злився

12

Це також може бути корисним: http://rush.heroku.com/

Я не дуже його використовував, але виглядає досить круто

З сайту:

rush - це заміна оболонки unix (bash, zsh тощо), яка використовує чистий синтаксис Ruby. Переглядайте файли, знаходьте та вбивайте процеси, копіюйте файли - все, що ви робите в оболонці, зараз у Ruby


2
Пік: ні. Чому? groups.google.com/group/ruby-shell/browse_thread/thread/… Чудово, але за кермом немає нікого.
Dan Rosenstark

12

скажімо, ви пишете свій script.rbсценарій. поставити:

#!/usr/bin/env ruby

як перший рядок і зробіть а chmod +x script.rb


7

Коли ви хочете написати більш складні сценарії рубіну, ці інструменти можуть допомогти:

Наприклад:

  • Тор (сценарій рамки)

  • gli (git like interface)

  • метадон (для створення простих інструментів)

Вони дозволяють швидко почати писати власні сценарії, особливо "додаток командного рядка".


5

Наведена вище відповідь цікава і дуже корисна при використанні Ruby як скрипту оболонки. Для мене я не використовую Ruby як свою щоденну мову, і я вважаю за краще використовувати рубін лише як контроль потоку і все ще використовую bash для виконання завдань.

Для тестування результату виконання може використовуватися деяка помічна функція

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

За допомогою помічника сценарій рубіну може бути схожим на:

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

Людина, це чудово, дякую!
Віктор Мартінс

4

"Як писати рубін" трохи виходить за рамки SO.

Але щоб перетворити ці сценарії рубіну у виконувані сценарії, поставте це як перший рядок сценарію ruby:

#!/path/to/ruby

Потім зробіть файл виконуваним:

chmod a+x myscript.rb

і геть ти йдеш.


4

Розмістіть це на початку вашого script.rb

#!/usr/bin/env ruby

Потім позначте його як виконуваний:

chmod +x script.rb

3

Відповідь вебматеріалу ідеальна. Я просто хочу вказати вам на додаток. Якщо вам доведеться багато працювати з параметрами командного рядка для ваших сценаріїв, вам слід використовувати optparse . Це просто і допомагає вам надзвичайно.


3

У рубіні константа __FILE__завжди надасть вам шлях сценарію, який ви виконуєте.

У Linux /usr/bin/envваш друг:

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

У Windows залежить, асоціюється чи ні .rb файли з рубіном. Якщо вони:

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

Якщо їх немає, вам потрібно явно викликати рубіни на них, я використовую проміжний .cmd файл:

my_script.cmd:

@ruby %~dp0\my_script.rb

my_script.rb:

puts File.expand_path(__FILE__)
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.