Jak używać Rubiego do tworzenia skryptów powłoki?

165

Mam kilka prostych zadań związanych ze skryptami powłoki, które chcę wykonać

Na przykład: Wybór pliku w katalogu roboczym z listy plików pasujących do jakiegoś wyrażenia regularnego.

Wiem, że mogę robić tego typu rzeczy używając standardowego basha i grepa, ale byłoby miło móc zhakować szybkie skrypty, które będą działać w systemie Windows i Linux bez konieczności zapamiętywania stosu programów wiersza poleceń i flag itp.

Próbowałem to osiągnąć, ale w końcu pomyliłem się, gdzie powinienem znaleźć informacje, takie jak odniesienie do bieżącego katalogu

Zatem pytanie brzmi, jakie części bibliotek Ruby muszę wiedzieć, aby pisać skrypty powłoki Ruby?

Willbill
źródło
3
Prawdopodobnie nie jest to dobra odpowiedź, ale praktyczny Ruby do administrowania systemem to świetne odniesienie. amazon.com/Practical-System-Administration-Experts-Source/dp/ ...
exiquio

Odpowiedzi:

148

Domyślnie masz już dostęp do katalogu i pliku , które same w sobie są całkiem przydatne.

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

Przydatne ze standardowej biblioteki jest również 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)

Co jest całkiem miłe

webmat
źródło
110

Jak już powiedzieli inni, twoja pierwsza linia powinna być

#!/usr/bin/env ruby

Musisz także uczynić go wykonywalnym: (w powłoce)

chmod +x test.rb

Następnie następuje kod ruby. Jeśli otworzysz plik

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

plik jest otwierany w bieżącym katalogu, który otrzymałeś pwdw powłoce.

Ścieżka do skryptu jest również łatwa do zdobycia. Otrzymasz $0pierwszy argument powłoki, który jest względną ścieżką do twojego skryptu. Ścieżkę bezwzględną można określić w następujący sposób:

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

Do operacji na systemie plików prawie zawsze używam Pathname. Jest to opakowanie dla wielu innych klas związanych z systemem plików. Przydatne również: Dir, File ...

Georg Schölly
źródło
66

Oto coś ważnego, czego brakuje w innych odpowiedziach: parametry wiersza poleceń są widoczne dla twojego skryptu powłoki Ruby poprzez tablicę ARGV (globalną).

Więc jeśli masz skrypt o nazwie my_shell_script:

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

... uczyń go wykonywalnym (jak wspominali inni):

chmod u+x my_shell_script

I nazwij to tak:

> ./my_shell_script one two three four five

Otrzymasz to:

I was passed: 
one
two
three
four
five

Argumenty działają dobrze z rozwijaniem nazw plików:

./my_shell_script *

I was passed: 
a_file_in_the_current_directory
another_file    
my_shell_script
the_last_file

Większość z nich działa tylko w systemie UNIX (Linux, Mac OS X), ale możesz zrobić podobne (choć mniej wygodne) rzeczy w systemie Windows.

Craig Walker
źródło
32

Jest tu wiele dobrych rad, więc chciałem dodać trochę więcej.

  1. Backticks (lub back-ticks) pozwalają znacznie łatwiej wykonać pewne czynności związane ze skryptami. Rozważać

    puts `find . | grep -i lib`
  2. Jeśli napotkasz problemy z pobieraniem danych wyjściowych z odwrotnych znaków, zawartość zostanie zwrócona do standardowego błędu zamiast standardowego wyjścia. Skorzystaj z tej rady

    out = `git status 2>&1`
  3. Backticks wykonują interpolację ciągów:

    blah = 'lib'
    `touch #{blah}`
    
  4. Możesz też potokować wewnątrz Rubiego . Jest to link do mojego bloga, ale prowadzi z powrotem tutaj, więc jest w porządku :) Prawdopodobnie są tam bardziej zaawansowane rzeczy na ten temat.

  5. Jak zauważyli inni, jeśli chcesz podejść na poważnie, jest Rush: nie tylko jako zamiennik powłoki (co jest dla mnie trochę zbyt szalone), ale także jako biblioteka do użytku w skryptach powłoki i programach.


Na Macu użyj Applescript w Rubim, aby uzyskać więcej mocy. Oto mój shell_hereskrypt:

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

`osascript -e "${cmd}"`
Dan Rosenstark
źródło
Musiałem tylko wciąć w kodzie 4 dodatkowe spacje, aby zostały sformatowane. Odłożyłem również znaki odwrotne, ale w ogóle nie znam dobrze Rubiego, więc będziesz chciał sprawdzić, czy to jest to, co zamierzałeś.
Bill the Lizard
@Bill the Lizard, tak, to była „sztuczka”, której potrzebowałem: podwójne wcięcia. DZIĘKI ZA POMOC.
Dan Rosenstark
1
Myślę, że Rush nie żyje: groups.google.com/group/ruby-shell/browse_thread/thread/…
Dan Rosenstark
22

Zdobądź kopię Everyday Scripting with Ruby . Zawiera wiele przydatnych wskazówek, jak robić rzeczy, które chcesz robić.

Aaron Hinni
źródło
2
Dobra książka, właśnie ją czytam: to jak podróż z kodem zen. A jeśli nie znasz TDD, przez cały czas nauczysz się podstaw TDD.
Sébastien RoccaSerra
Myślę, że książka zawiera dobre informacje, ale dla doświadczonych programistów zbyt duże obciążenie.
D połączył się
12

Może to być również pomocne: http://rush.heroku.com/

Nie używałem go zbyt często, ale wygląda całkiem fajnie

Ze strony:

rush jest zamiennikiem powłoki unixowej (bash, zsh itp.), która używa czystej składni Rubiego. Przeglądaj pliki, znajduj i zabijaj procesy, kopiuj pliki - wszystko, co robisz w powłoce, teraz w Rubim

craigp
źródło
2
Rush: nie. Czemu? groups.google.com/group/ruby-shell/browse_thread/thread/… Jest super, ale za kierownicą nie ma nikogo.
Dan Rosenstark
12

powiedzmy, że piszesz swój script.rbscenariusz. położyć:

#!/usr/bin/env ruby

jako pierwszą linię i wykonaj chmod +x script.rb

Wasilij
źródło
7

Jeśli chcesz pisać bardziej złożone skrypty ruby, pomocne mogą być te narzędzia:

Na przykład:

  • thor (framework skryptowy)

  • gli (interfejs podobny do git)

  • metadon (do tworzenia prostych narzędzi)

Umożliwiają one szybkie rozpoczęcie pisania własnych skryptów, zwłaszcza „aplikacji wiersza poleceń”.

Bohr
źródło
5

Powyższa odpowiedź jest interesująca i bardzo pomocna podczas używania Rubiego jako skryptu powłoki. Dla mnie nie używam Ruby jako mojego codziennego języka i wolę używać Ruby tylko jako kontroli przepływu i nadal używam basha do wykonywania zadań.

Do testowania wyniku wykonania można użyć funkcji pomocniczych

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

Z pomocnikiem skrypt ruby ​​mógłby być podobny do basha:

#!/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
Houcheng
źródło
Człowieku, to świetnie, dziękuję!
Victor Martins
4

„Jak napisać ruby” jest trochę poza zakresem SO.

Ale aby zamienić te skrypty ruby ​​w skrypty wykonywalne, umieść to jako pierwszą linię skryptu ruby:

#!/path/to/ruby

Następnie ustaw plik wykonywalny:

chmod a+x myscript.rb

i odejdź.

Matthew Scharley
źródło
4

Umieść to na początku swojego script.rb

#!/usr/bin/env ruby

Następnie oznacz go jako wykonywalny:

chmod +x script.rb
Daniel Beardsley
źródło
3

Odpowiedź dostarczona przez webmat jest doskonała. Chcę tylko wskazać dodatek. Jeśli masz dużo do czynienia z parametrami wiersza poleceń dla swoich skryptów, powinieneś użyć optparse . Jest to proste i niezwykle pomocne.

awenkhh
źródło
3

W ruby, stała __FILE__zawsze podaje ścieżkę do uruchomionego skryptu.

W Linuksie /usr/bin/envjest twoim przyjacielem:

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

W systemie Windows zależy to od tego, czy pliki .rb są powiązane z ruby. Jeśli są:

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

Jeśli tak nie jest, musisz jawnie wywołać na nich ruby, używam pośredniego pliku .cmd:

my_script.cmd:

@ruby %~dp0\my_script.rb

my_script.rb:

puts File.expand_path(__FILE__)
bltxd
źródło