我正在尝试将我正在从事的学生工作中一些乏味的部分自动化。
基本上,目标是克隆一堆 git 存储库(我已经在工作了),然后对所有这些存储库运行相同的 git checkout。每次,我都会收到这样的信息:
`git rev-list -n 1 --before="2016-04-29 23:59" master`
提供给 git checkout。我想将整个事情传递到我的脚本中,以便它可以为我进行结账。目前,我的脚本是
#!/bin/bash
echo $1
(它最初比较复杂,但我后来注释掉了其他所有内容,这样我就可以专注于这个输入。)
当我尝试运行脚本时:
./RepoScan `git rev-list -n 1 --before="2016-04-29 23:59" master`
我收到以下错误:
fatal: Not a git repository (or any of the parent directories): .git
随后是换行符。我认为这意味着 git rev-list 正在尝试运行,而不是传递给 RepoScan。有没有办法打包它,以便它在作为参数输入时不会运行,但仍然可以由脚本运行?
(另外,我正在使用 OSX,如果这很重要的话。)
答案1
反引号分隔 a命令替换:执行反引号内的命令,并将其输出插入到命令行中。 (如果反引号不在双引号内,则会出现进一步的复杂情况,稍后会详细介绍。)因此,发生的情况是在运行git rev-list …
之前在当前目录中执行。RepoScan
不可能是其他情况,因为git
命令的输出作为参数传递给RepoScan
.
如果要RepoScan
运行调用时指定的命令,则需要传递该命令在 的命令行上RepoScan
,而不是该命令的输出。有两种方法可以做到这一点,具体取决于您所指的命令的含义。
传递带有参数的可执行文件
如果要将该命令解释为带有某些参数的可执行文件,则将该命令作为单词列表。
./RepoScan git rev-list -n 1 --before="2016-04-29 23:59" master
在RepoScan
脚本中,使用"$@"
来引用命令。该@
符号是一个特殊变量,代表参数列表。当在双引号内使用时,它有一个特殊的行为:每个参数都放在一个单独的单词中,这"$@"
相当于列表的论点。
如果该RepoScan
命令采用其他选项,则它们都必须在该命令之前传递。使用shift
内置函数从命令行开头删除已处理的选项。您通常会使用getopts
内置解析选项。
传递 shell 片段
另一种可能性是将 shell 程序片段作为单个参数传递。
./RepoScan 'git rev-list -n 1 --before="2016-04-29 23:59" master'
请注意这次引用的两个级别。单引号用于您正在调用的 shell RepoScan
;单引号内的所有内容均按字面解释,因此RepoScan
得到一个参数,即 string git rev-list -n 1 --before="2016-04-29 23:59" master
。在里面RepoScan
,因为你有一个 shell 片段,所以用
eval "$1"
如果片段位于第一个参数中,或者
eval "$command"
如果代码片段在变量中command
。
注意变量扩展周围的双引号。这是必要的,因为$foo
外部双引号并不意味着“ 的值foo
”,而是“取 的值foo
,根据 拆分它IFS
并将结果解释为 glob 模式列表”(也称为 split+glob 运算符)。