我正在编写一个Ruby脚本,它可以执行一些简单的git命令。我想列出我的应用程序目录中没有的所有文件更改。
运行以下命令以获取终端中的所有更改:
git ls-files -m
产量:
config/environment.rb
app/models/site.rb
在终端中使用通配符异常运行:
git ls-files -m !(app)
产量:
config/environment.rb
使用以下方法在Ruby中执行相同的操作:
`git ls-files -m !(app)`
产量:
sh: -c: line 0: syntax error near unexpected token `('
sh: -c: line 0: `git ls-files -m !(app)'
我试过增加双逃逸:
`git ls-files -m \\!\\(app\\)`
不会产生错误,只会产生空的结果。
我也试过使用Shellword:
require 'shellwords'
`git ls-files -m #{Shellwords.escape("!(app)")}`
不会产生错误,只会产生空的结果。
使用%x[]
语法的行为也与backticks完全一样,但似乎不像我所希望的那样工作。
有什么想法吗?如何通过在Ruby中运行git ls-files -m !(app)
获得相同的结果?
发布于 2015-02-05 04:42:19
!(app)
是一个bash扩展的全局。所以有两个问题:
ruby
使用sh
来执行系统命令,而不是bash
。(您可以在错误消息中看到这一点,该消息声称来自sh:
。)但是,由于您的sh
是由bash
实现的,所以您确实可以使用bash,但有一个小问题:当bash
作为sh
运行时,它会禁用许多特定于bash的特性。bash
,也很可能没有执行shopt -s extglob
,这是!(app)
和其他扩展全局运行所必需的。默认情况下,扩展全局不启用,但是一些发行版(例如,ubuntu)启用它们以实现选项卡完成,因此您可能在交互式shell中启用了它们。但是,由于ruby没有调用交互式shell,很可能没有执行带有shopt -s extglob
命令的bash启动文件。所有这一切都不可能通过红宝石使用命令,但它肯定会使生活复杂化。例如,一个可能的解决方法是启用BASHOPTS并强制bash
运行:
`env BASHOPTS=$BASHOPTS:extglob bash -c 'git ls-files -m !(app)'`
这可能比使用grep -v
过滤掉不需要的目录名的替代解决方案复杂得多。
使用env
设置env
实际上只有在/bin/sh
实际上是bash
的情况下才能工作,因此在执行的命令中直接设置shopt
可能更好。这是直截了当的,但也有一个小问题;您需要在shopt
命令和扩展glob的使用之间引入一条换行符,因为bash标记一次命令一行(如果extglob
在标记时没有设置,那么(
就是一个元字符)。
这似乎是可行的:
`bash -c "shopt -s extglob\ngit ls-files -m !(app)"`
https://stackoverflow.com/questions/28336202
复制相似问题