这是我的剧本
#!/usr/bin/env ruby
if __FILE__ == $0
`cd ..`
puts `ls`
end
Run Code Online (Sandbox Code Playgroud)
运行良好,但当它退出时,我回到我开始的地方.如何"导出"我对环境所做的更改?
那是因为```运算符不适用于复杂的脚本.它对于运行单个命令(并读取其输出)很有用.它后面没有shell来存储它的调用之间和Ruby脚本终止后的环境变化.
在Linux系统上,每个进程都有自己的"当前目录"路径(可以在/ proc/<pid>/cwd中找到).更改进程中的目录不会影响父进程(从中运行程序的shell).如果cd内置是二进制的,它只能更改自己的当前目录,而不是父进程之一(这就是为什么cd命令只能内置).
如果必须从shell执行Ruby脚本并且必须影响shell的当前目录路径,则可以制作"技巧".不是从Ruby本身运行命令,而是将命令打印到stdout,然后打印到source运行Ruby脚本的shell.命令不会由shell的单独进程执行,因此所有cds 都将在当前shell实例中生效.
所以,而不是
ruby run_commands.rb
Run Code Online (Sandbox Code Playgroud)
在shell脚本中写下这样的东西:
source <(ruby prepare_and_print_commands.rb)
Run Code Online (Sandbox Code Playgroud)
Shell 类但是Ruby中有一个方便的命令行脚本工具 - Shell类!它已经预先定义常用命令的起酥油(如cd,pwd,cat,echo等),并允许定义自己的(它支持的命令和别名)!此外,它透明地支持使用输入/输出的重定向|,>,<,>>,<<Ruby操作符.
在Shell大多数情况下,使用是不言自明的.看看几个简单的例子.
创建"shell"对象并更改目录
sh = Shell.new
sh.cd '~/tmp'
# or
sh = Shell.cd('~/tmp')
Run Code Online (Sandbox Code Playgroud)
在当前目录中工作
puts "Working directory: #{sh.pwd}"
(sh.echo 'test') | (sh.tee 'test') > STDOUT
# Redirecting possible to "left" as well as to "right".
(sh.cat < 'test') > 'triple_test'
# '>>' and '<<' are also supported.
sh.cat('test', 'test') >> 'triple_test'
Run Code Online (Sandbox Code Playgroud)
(注意,有时必须使用括号,因为"重定向"运算符的优先级.默认情况下,命令输出不会打印到stdout,因此您需要指定使用> STDOUT,或者> STDERR如果需要.)
测试文件属性
puts sh.test('e', 'test')
# or
puts sh[:e, 'test']
puts sh[:exists?, 'test']
puts sh[:exists?, 'nonexistent']
Run Code Online (Sandbox Code Playgroud)
(与test普通shell中的函数类似.)
定义自定义命令和别名
# name command line to execute
Shell.def_system_command 'list', 'ls -1'
# name cmd command's arguments
Shell.alias_command "lsC", "ls", "-CBF"
Shell.alias_command("lsC", "ls") { |*opts| ["-CBF", *opts] }
Run Code Online (Sandbox Code Playgroud)
定义的命令的名称稍后可以用来精确地运行它以同样的方式,因为它适用于预定义echo或cat,例如.
使用目录堆栈
sh.pushd '/tmp'
sh.list > STDOUT
(sh.echo sh.pwd) > STDOUT
sh.popd
sh.list > STDOUT
(sh.echo sh.pwd) > STDOUT
Run Code Online (Sandbox Code Playgroud)
(这里list使用上面定义的自定义命令.)
顺便说一下,有一个有用的chdir命令可以在目录中运行几个命令,然后返回到之前的工作目录.
puts sh.pwd
sh.chdir('/tmp') do
puts sh.pwd
end
puts sh.pwd
Run Code Online (Sandbox Code Playgroud)
跳过一组命令的shell对象
# Code above, rewritten to drop out 'sh.' in front of each command.
sh.transact do
pushd '/tmp'
list > STDOUT
(echo pwd) > STDOUT
popd
list > STDOUT
(echo pwd) > STDOUT
end
Run Code Online (Sandbox Code Playgroud)
附加功能
另外Shell还有:
foreach 迭代文件中的行或通过目录中的文件列表的方法(取决于给定的路径指向文件或目录),jobs和kill控制进程的命令,basename,chmod,chown,delete,dirname,rename,stat,symlink),File的方法的同义词(directory?,executable?,exists?,readable?,等等),FileTest类的方法(syscopy,copy,move,compare,safe_unlink,makedirs,install).