2008-10-03 121 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