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


165

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

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

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

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

Итак, вопрос в том, какие части библиотек Ruby мне нужно знать, чтобы писать сценарии оболочки 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, File ...


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 пробела для их форматирования. Я также поставил обратно галочки, но я не очень хорошо знаю Ruby, так что вы захотите проверить, чтобы убедиться, что это то, что вы хотели.
Билл Ящерица

@ Билл Ящерица, да, это был «трюк», который мне был нужен: двойной отступ. СПАСИБО ЗА ПОМОЩЬ.
Дэн Розенстарк


22

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


2
Хорошая книга, я читаю ее прямо сейчас: похоже на путешествие по дзен-коду. И если вы не знаете, TDD, вы будете изучать основы TDD на всем пути.
Себастьян РоккаСерра

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

12

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

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

С сайта:

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


2
Раш: нет. Зачем? groups.google.com/group/ruby-shell/browse_thread/thread/… Это здорово, но за рулем никого нет.
Дэн Розенстарк

12

допустим, вы пишете свой script.rbсценарий. ставить:

#!/usr/bin/env ruby

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


7

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

Например:

  • thor (среда сценариев)

  • gli (git like interface)

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

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


5

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

Чувак, это здорово, спасибо!
Виктор Мартинс

4

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

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

#!/path/to/ruby

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

chmod a+x myscript.rb

и понеслось.



3

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


3

В ruby ​​константа __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 с 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__)
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.