Как использовать Ruby для сценариев оболочки?

У меня есть несколько простых задач сценария для скриптов, которые я хочу сделать

Например: выбор файла в рабочем каталоге из списка файлов, соответствующих некоторому регулярному выражению.

Я знаю, что могу делать подобные вещи с помощью стандартных bash и grep, но мне было бы неплохо взломать быстрые скрипты, которые будут работать в Windows и Linux, без необходимости запоминать кучу программ командной строки и флагов и т.д.

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

Итак, вопрос в том, какие части библиотек Ruby мне нужно знать для написания сценариев оболочки ruby?

Ответ 1

По умолчанию у вас уже есть доступ к 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)

Что довольно приятно

Ответ 2

Как уже говорили другие, ваша первая строка должна быть

#!/usr/bin/env ruby

И вы также должны сделать его исполняемым: (в оболочке)

chmod +x test.rb

Далее следует код ruby. Если вы откроете файл

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

файл открывается в текущем каталоге, который вы получите с помощью pwd в оболочке.

Путь к вашему script также прост. С помощью $0 вы получите первый аргумент оболочки, который является относительным путем к вашему script. Абсолютный путь можно определить следующим образом:

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

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

Ответ 3

Здесь что-то важное, что отсутствует в других ответах: параметры командной строки отображаются в оболочке Ruby script через массив ARGV (глобальный).

Итак, если у вас есть script, называемый 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.

Ответ 4

Здесь много хорошего совета, поэтому я хотел добавить немного больше.

  1. Backticks (или back-ticks) позволяют вам делать некоторые сценарии намного проще. Рассматривать

    puts 'find . | grep -i lib'
    
  2. Если у вас возникнут проблемы с получением выходных данных, материал будет заменен стандартным err вместо стандартного. Используйте этот совет

    out = 'git status 2>&1'
    
  3. Backticks выполняет строчную интерполяцию:

    blah = 'lib'
    'touch #{blah}'
    
  4. Вы можете трубить внутри Ruby. Это ссылка на мой блог, но он ссылается сюда, так что все в порядке :) Есть, вероятно, более продвинутые вещи на этой теме.

  5. Как отмечали другие люди, если вы хотите серьезно стать, есть Rush: не только как замена оболочки (что для меня слишком заодно), но и как библиотека для вашего использования в сценариях и программах оболочки.


На Mac, используйте Applescript внутри Ruby для большей мощности. Вот мой скрипт shell_here:

#!/usr/bin/env ruby
'env | pbcopy' 
cmd =  %[email protected] app "Terminal" to do script "$(paste_env)"@
puts cmd

'osascript -e "${cmd}"'

Ответ 5

Пойдите, сделайте себе копию Everyday Scripting with Ruby. В нем есть много полезных советов о том, как делать типы вещей, которые вы хотите сделать.

Ответ 6

Это также может быть полезно: http://rush.heroku.com/

Я не использовал его много, но выглядит довольно круто.

С сайта:

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

Ответ 7

скажем, вы пишете свой script.rb script. говоря:

#!/usr/bin/env ruby

в качестве первой строки и выполните chmod +x script.rb

Ответ 8

Если вы хотите написать более сложные рубиновые скрипты, эти инструменты могут помочь:

Например:

  • thor (структура сценариев)

  • gli (git как интерфейс)

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

Они дают вам быстрый старт для написания собственных сценариев, особенно "приложение командной строки".

Ответ 9

"Как написать ruby" немного выходит за рамки SO.

Но чтобы превратить эти рубиновые скрипты в исполняемые скрипты, поставьте это как первую строку вашего ruby ​​ script:

#!/path/to/ruby

Затем сделайте исполняемый файл:

chmod a+x myscript.rb

и уходите.

Ответ 10

Поместите это в начало вашего script.rb

#!/usr/bin/env ruby

Затем отметьте его как исполняемый файл:

chmod +x script.rb

Ответ 11

В ruby ​​константа __FILE__ всегда даст вам путь к script, который вы используете.

В 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 с ruby. Если они:

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

Если это не так, вы должны явно вызвать ruby ​​на них, я использую промежуточный файл .cmd:

my_script.cmd:

@ruby %~dp0\my_script.rb

my_script.rb:

puts File.expand_path(__FILE__)

Ответ 12

Ответ webmat является идеальным. Я просто хочу указать вам на дополнение. Если вам приходится иметь дело с параметрами командной строки для ваших скриптов, вы должны использовать optparse. Это просто и очень помогает вам.

Ответ 13

Вышеуказанный ответ интересен и очень полезен при использовании Ruby в качестве оболочки script. Для меня я не использую 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

С помощником ruby ​​ script может быть 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