如何使用 Ruby 编写 shell 脚本?

我有一些简单的 shell 脚本任务,我想做

例如: 从匹配某个正则表达式的文件列表中选择工作目录中的一个文件。

我知道我可以使用标准的 bash 和 grep 来做这些事情,但是我希望能够编写一些快速的脚本,这些脚本可以在 windows 和 linux 中工作,而不需要我去记住一堆命令行程序和标志等等。

我试图让这个过程继续下去,但最终还是搞不清楚应该从哪里获取信息,比如哪里有关于工作目录的参考信息

所以问题是我需要知道 Ruby 库的哪些部分来编写 Ruby shell 脚本?

134188 次浏览

“ How do I write ruby”有点超出了 SO 的范围。

但是要将这些 Ruby 脚本转换为可执行脚本,请将以下内容作为 Ruby 脚本的第一行:

#!/path/to/ruby

然后使文件可执行:

chmod a+x myscript.rb

开始吧。

假设你写了你的 script.rb脚本:

#!/usr/bin/env ruby

作为第一行,做一个 chmod +x script.rb

把这个放在 script.rb 的开头

#!/usr/bin/env ruby

然后将其标记为可执行文件:

chmod +x script.rb

正如其他人已经说过的,你的第一句台词应该是

#!/usr/bin/env ruby

而且您还必须使它可执行: (在 shell 中)

chmod +x test.rb

然后按照红宝石代码。如果你打开一个文件

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

这个文件打开的工作目录是你在 shell 中看到的 pwd

获取脚本的路径也很简单。使用 $0可以得到 shell 的第一个参数,这是到脚本的相对路径。绝对路径可以这样确定:

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

对于文件系统操作,我几乎总是使用 Pathname。这是许多其他文件系统相关类的包装器。也有用: 目录,文件..。

在 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 文件:

我的 _ script. cmd:

@ruby %~dp0\my_script.rb

我的 _ script. rb:

puts File.expand_path(__FILE__)

去给自己买一份 使用 Ruby 编写日常脚本。它有很多关于如何做你想做的事情的有用的提示。

默认情况下,您已经可以访问 长官档案,它们本身非常有用。

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)

挺不错的

这可能也有帮助: http://rush.heroku.com/

我没怎么用过,不过看起来很酷

来自网站:

Rush 是 Unix shell (bash、 zsh 等)的替代品,后者使用纯 Ruby 语法。浏览文件、查找和终止进程、复制文件——所有你在 shell 中做的事情,现在在 Ruby 中

这里有一些其他答案中缺少的重要内容: 命令行参数通过 ARGV (global)数组公开给 Ruby shell 脚本。

因此,如果您有一个名为 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,MacOSX)上运行,但是您可以在 Windows 中做类似的事情(尽管不那么方便)。

这里有很多好的建议,所以我想多加一点。

  1. Backticks (或 Backticks)让您更容易地编写脚本

    puts `find . | grep -i lib`
    
  2. If you run into problems with getting the output of backticks, the stuff is going to standard err instead of standard out. Use this advice

    out = `git status 2>&1`
    
  3. Backticks do string interpolation:

    blah = 'lib'
    `touch #{blah}`
    
  4. You can pipe inside Ruby, too. It's a link to my blog, but it links back here so it's okay :) There are probably more advanced things out there on this topic.

  5. As other people noted, if you want to get serious there is Rush: not just as a shell replacement (which is a bit too zany for me) but also as a library for your use in shell scripts and programs.


On Mac, Use Applescript inside Ruby for more power. Here's my shell_here script:

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


`osascript -e "${cmd}"`

网络应用软件的答案是完美的。我只是想给你们指出一点。如果需要为脚本处理很多命令行参数,那么应该使用 Optparse。它很简单,对你有很大的帮助。

如果您想编写更复杂的 Ruby 脚本,这些工具可能会有所帮助:

例如:

它们可以让你快速开始编写自己的脚本,特别是“命令行应用程序”。

上面的答案很有趣,在使用 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

使用 helper,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