2008-10-03 137 views
156

我有一些簡單的shell腳本任務,我想要做如何使用Ruby進行shell腳本?

例如:從與某些正則表達式匹配的文件列表中選擇工作目錄中的文件。

我知道我可以使用標準的bash和grep來做這種事情,但是我會很高興能夠破解在windows和linux下工作的快速腳本,而不必記住一堆命令行程序和標誌等

我試圖讓這個打算,但最終弄不清,我應該得到的信息,如當前目錄

參考所以,問題是什麼Ruby庫的一部分,我需要知道寫紅寶石shell腳本?

+2

可能不是一個很好的答案,但實用的Ruby進行系統管理是一個很好的參考。 http://www.amazon.com/Practical-System-Administration-Experts-Source/dp/1590598210/ref=sr_1_1?s=books&ie=UTF8&qid=1346355414&sr=1-1&keywords=ruby+for+system+administration – exiquio 2012-08-30 19:38:55

回答

141

默認情況下,您已經有權訪問DirFile,它們本身非常有用。

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) 

這是相當不錯的

4

「我怎麼寫紅寶石」有點超出了SO的範圍。

但把這些Ruby腳本轉換爲可執行的腳本,把這個作爲你的Ruby腳本的第一行:

#!/path/to/ruby 

然後使文件可執行:

chmod a+x myscript.rb 

和遠離你去。

9

假設你編寫你的script.rb腳本。放:

#!/usr/bin/env ruby 

的第一線,做一個chmod +x script.rb

4

將這個你script.rb年初

#!/usr/bin/env ruby 

然後將其標記爲可執行:

chmod +x script.rb 
103

正如其他人所說,你的第一行應該是

#!/usr/bin/env ruby 

而且你還必須使其可執行:(中殼)

chmod +x test.rb 

然後跟隨Ruby代碼。如果你打開一個文件

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

該文件是在當前目錄中打開你會在外殼pwd得到。

腳本的路徑也很容易獲得。使用$0,您將獲得shell的第一個參數,它是腳本的相對路徑。絕對路徑可以這樣確定:

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

對於文件系統操作,我幾乎總是使用路徑名。這是許多其他文件系統相關類的包裝器。還有用:Dir,File ...

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文件與紅寶石有關。 如果他們是:

# 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__) 
21

去找一份Everyday Scripting with Ruby 。它有很多關於如何做你想做的事情的有用技巧。

+1

好書,我現在正在閱讀它:它感覺就像一個禪碼之旅。如果您不瞭解TDD,您將學習TDD的基本知識。 – 2010-03-16 11:09:47

+0

我認爲這本書有一些很好的信息,但對於有經驗的程序員來說要花費太多。 – 2014-01-08 07:16:43

12

這也可能會有所幫助:http://rush.heroku.com/

我沒有用它不多,但看起來很酷

來自網站:

rush是使用純Ruby語法的unix shell(bash,zsh等)的替代品。通過文件的grep,找到並殺死進程,複製文件 - 所有你在外殼上進行,現在在Ruby中

+2

Rush:沒有。爲什麼? http://groups.google.com/group/ruby-shell/browse_thread/thread/75c8cea757d2f680#這很棒,但沒有人在駕駛。 – 2010-04-04 09:56:54

65

這裏的東西很重要的就是從其他的答案丟失:命令行參數都暴露在你的Ruby shell腳本通過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中執行類似的操作(儘管不太方便)。

30

有很多很好的意見在這裏,所以我想添加更多的一點點。

  1. 反斜杆(或反勾號)讓你做一些腳本的東西容易得多。考慮

    puts `find . | grep -i lib` 
    
  2. 如果遇到與得到反引號的輸出問題,東西是要標準錯誤而不是標準輸出。 Use this advice

    out = `git status 2>&1` 
    
  3. 反引號做字符串插值:

    blah = 'lib' 
    `touch #{blah}` 
    
  4. You can pipe inside Ruby, too。這是我的博客的鏈接,但鏈接回到這裏,所以它的好:)可能有更先進的東西在那裏對這個話題。

  5. 正如其他人所指出的,如果你不想太認真也拉什:不只是作爲一個外殼更換(這對我來說有點太滑稽),而且還as a library for your use in shell scripts and programs.


在Mac,在Ruby中使用Applescript以獲得更多的功能。這裏是我的shell_here腳本:

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

`osascript -e "${cmd}"` 
3

答案由webmat是完美的。我只是想指出你的一個補充。如果你要處理很多與命令行參數的腳本,你應該使用optparse。它非常簡單,並且非常有幫助。

6

當你想要編寫更復雜的Ruby腳本,這些工具可以幫助:

例如:

  • thor(腳本框架)

  • gli(GIT一樣的界面)

  • methadone(用於創建簡單工具)

它們讓您快速編寫自己的腳本,特別是「命令行應用程序」。

3

以上答案在使用Ruby作爲shell腳本時非常有趣且非常有用。對我而言,我並不使用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