Bagaimana cara menggunakan Ruby untuk skrip shell?

165

Saya memiliki beberapa tugas skrip shell sederhana yang ingin saya lakukan

Misalnya: Memilih file di direktori kerja dari daftar file yang cocok dengan ekspresi reguler.

Saya tahu bahwa saya dapat melakukan hal semacam ini dengan menggunakan standar bash dan grep tetapi saya akan senang dapat meretas skrip cepat yang akan bekerja di windows dan linux tanpa saya harus menghafal tumpukan program command line dan bendera dll.

Saya mencoba menjalankan ini tetapi akhirnya menjadi bingung di mana saya seharusnya mendapatkan informasi seperti referensi ke direktori saat ini

Jadi pertanyaannya adalah apa bagian dari pustaka Ruby yang perlu saya ketahui untuk menulis skrip ruby ​​shell?

Willbill
sumber
3
Mungkin bukan jawaban yang baik, tetapi Ruby Praktis untuk Administrasi Sistem adalah referensi yang bagus. amazon.com/Practical-System-Administration-Experts-Source/dp/…
exiquio

Jawaban:

148

Secara default, Anda sudah memiliki akses ke Dir dan File , yang cukup berguna sendiri.

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

Juga berguna dari stdlib adalah 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)

Cukup bagus

webmat
sumber
110

Seperti yang sudah dikatakan orang lain, baris pertama Anda seharusnya

#!/usr/bin/env ruby

Dan Anda juga harus membuatnya dapat dieksekusi: (di shell)

chmod +x test.rb

Kemudian ikuti kode ruby. Jika Anda membuka file

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

file dibuka di direktori saat ini Anda akan dapatkan pwddi shell.

Jalur ke skrip Anda juga mudah didapat. Dengan $0Anda mendapatkan argumen pertama dari shell, yang merupakan jalur relatif ke skrip Anda. Jalan absolut dapat ditentukan seperti itu:

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

Untuk operasi sistem file, saya hampir selalu menggunakan Pathname. Ini adalah pembungkus untuk banyak kelas terkait sistem file lainnya. Juga berguna: Dir, File ...

Georg Schölly
sumber
66

Berikut adalah sesuatu yang penting yang hilang dari jawaban lain: parameter baris perintah diekspos ke skrip shell Ruby Anda melalui array ARGV (global).

Jadi, jika Anda memiliki skrip bernama my_shell_script:

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

... membuatnya dapat dieksekusi (seperti yang telah disebutkan orang lain):

chmod u+x my_shell_script

Dan menyebutnya seperti ini:

> ./my_shell_script one two three four five

Anda akan mendapatkan ini:

I was passed: 
one
two
three
four
five

Argumen bekerja dengan baik dengan ekspansi nama file:

./my_shell_script *

I was passed: 
a_file_in_the_current_directory
another_file    
my_shell_script
the_last_file

Sebagian besar ini hanya bekerja pada UNIX (Linux, Mac OS X), tetapi Anda dapat melakukan hal-hal serupa (meskipun kurang nyaman) di Windows.

Craig Walker
sumber
32

Ada banyak saran bagus di sini, jadi saya ingin menambahkan sedikit lebih banyak.

  1. Backticks (atau back-ticks) memungkinkan Anda melakukan beberapa hal penulisan skrip dengan lebih mudah. Mempertimbangkan

    puts `find . | grep -i lib`
  2. Jika Anda mengalami masalah dengan mendapatkan output dari backticks, barang-barang akan menjadi standar err bukannya standar keluar. Gunakan saran ini

    out = `git status 2>&1`
  3. Backticks melakukan interpolasi string:

    blah = 'lib'
    `touch #{blah}`
  4. Anda dapat memasang pipa di dalam Ruby juga . Ini tautan ke blog saya, tetapi tautannya kembali ke sini jadi tidak apa-apa :) Mungkin ada hal-hal yang lebih maju di luar sana tentang topik ini.

  5. Seperti yang dicatat orang lain, jika Anda ingin serius ada Rush: tidak hanya sebagai pengganti shell (yang agak terlalu lucu bagi saya) tetapi juga sebagai perpustakaan untuk digunakan dalam skrip dan program shell.


Di Mac, Gunakan Applescript di dalam Ruby untuk kekuatan yang lebih besar. Ini shell_hereskrip saya :

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

`osascript -e "${cmd}"`
Dan Rosenstark
sumber
Saya hanya perlu indentasi kode 4 lebih banyak ruang untuk diformat. Saya juga mengembalikan backticks, tapi saya tidak tahu sama sekali tentang Ruby, jadi Anda harus memeriksa untuk memastikan itu yang Anda maksud.
Bill the Lizard
@Bill the Lizard, yeah, itu 'trik' yang saya butuhkan: indentasi ganda. TERIMA KASIH UNTUK BANTUANNYA.
Dan Rosenstark
1
Saya pikir Rush sudah mati: groups.google.com/group/ruby-shell/browse_thread/thread/…
Dan Rosenstark
22

Ambil sendiri salinan Everyday Scripting dengan Ruby . Ini memiliki banyak tips berguna tentang cara melakukan jenis hal yang ingin Anda lakukan.

Aaron Hinni
sumber
2
Buku bagus, saya membacanya sekarang: rasanya seperti perjalanan kode zen. Dan jika Anda tidak tahu TDD, Anda akan mempelajari dasar-dasar TDD sepanjang jalan.
Sébastien RoccaSerra
Saya pikir buku ini memiliki beberapa informasi yang bagus tetapi terlalu banyak untuk programmer yang berpengalaman.
The D Digabung
12

Ini mungkin juga membantu: http://rush.heroku.com/

Saya belum sering menggunakannya, tetapi terlihat sangat keren

Dari situs:

rush adalah pengganti shell unix (bash, zsh, dll) yang menggunakan sintaksis Ruby murni. Grep melalui file, temukan dan matikan proses, salin file - semua yang Anda lakukan di shell, sekarang di Ruby

craigp
sumber
2
Terburu-buru: tidak. Mengapa? groups.google.com/group/ruby-shell/browse_thread/thread/… Ini bagus tetapi tidak ada seorang pun di belakang kemudi.
Dan Rosenstark
12

katakanlah Anda menulis script.rbskrip Anda . taruh:

#!/usr/bin/env ruby

sebagai baris pertama dan lakukan a chmod +x script.rb

Vasil
sumber
7

Saat Anda ingin menulis skrip ruby ​​yang lebih rumit, alat ini dapat membantu:

Sebagai contoh:

  • thor (kerangka kerja scripting)

  • gli (git like interface)

  • metadon (untuk membuat alat sederhana)

Mereka memberi Anda awal yang cepat untuk menulis skrip Anda sendiri, terutama 'aplikasi command line'.

Bohr
sumber
5

Jawaban di atas menarik dan sangat membantu saat menggunakan Ruby sebagai skrip shell. Bagi saya, saya tidak menggunakan Ruby sebagai bahasa harian saya dan saya lebih suka menggunakan ruby ​​sebagai kontrol aliran saja dan masih menggunakan bash untuk melakukan tugas.

Beberapa fungsi pembantu dapat digunakan untuk menguji hasil eksekusi

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

Dengan helper, skrip ruby ​​bisa mirip:

#!/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
sumber
Sobat, ini bagus, terima kasih!
Victor Martins
4

"Bagaimana cara menulis ruby" sedikit di luar cakupan SO.

Tetapi untuk mengubah skrip ruby ​​ini menjadi skrip yang dapat dieksekusi, cantumkan ini sebagai baris pertama skrip ruby ​​Anda:

#!/path/to/ruby

Kemudian buat file tersebut dapat dieksekusi:

chmod a+x myscript.rb

dan pergilah.

Matthew Scharley
sumber
4

Tempatkan ini di awal skrip Anda.rb

#!/usr/bin/env ruby

Kemudian tandai sebagai executable:

chmod +x script.rb
Daniel Beardsley
sumber
3

Jawaban oleh webmat sempurna. Saya hanya ingin menunjukkan Anda tambahan. Jika Anda harus banyak berurusan dengan parameter baris perintah untuk skrip Anda, Anda harus menggunakan optparse . Ini sederhana dan sangat membantu Anda.

awenkhh
sumber
3

Dalam ruby, konstanta __FILE__akan selalu memberi Anda jalan naskah yang Anda jalankan.

Di Linux, /usr/bin/envadalah teman Anda:

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

Pada Windows, tergantung apakah file .rb dikaitkan dengan ruby ​​atau tidak. Jika mereka adalah:

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

Jika tidak, Anda harus secara eksplisit memanggil ruby, saya menggunakan file .cmd perantara:

my_script.cmd:

@ruby %~dp0\my_script.rb

my_script.rb:

puts File.expand_path(__FILE__)
bltxd
sumber