我试图将git ls-files与文件模式一起使用,以获得经过筛选的跟踪文件列表。(我知道我可以用grep et做下面的事情。但是我很好奇为什么它不起作用)
#!/usr/bin/env bash
GIT_ROOT=$(git rev-parse --show-toplevel)
# only include stuff in src and include
SRC_PATTERNS="{include,src}/**/*.{hpp,cpp,tpp,h,c}"
# @brief Get list of files in git index with names relative to root
# @param $1 Any of the constraints git-ls-files knows (e.g. --cached)
function git_sources()
{
FILE_STRING=$(git -C $GIT_ROOT ls-files --full-name $1 $SRC_PATTERNS)
echo "$FILE_STRING"
}我使用的glob在从命令行调用git ls-files命令时工作。
git -C $GIT_ROOT ls-files --full-name --cached {include,src}/**/*.{hpp,cpp,tpp,h,c}但在获取脚本后调用git_sources命令时就不行了。
问题:如何正确引用glob模式,以便将其传递给子命令,就像直接从命令行调用一样?
发布于 2019-06-24 10:25:21
这可能是因为shell如何扩展存储在变量中的glob字符串。无论使用哪种引号,shell都不会将包含glob字符串的命令展开到可以应用筛选器的结果文件中。
shell将在展开未引用的变量后进行全局化,但因为支撑展开是在变量展开之前完成的(参考文献)。( 壳展开),则glob将找不到任何匹配的文件,而shell将留下文字glob字符串。
当你跑的时候
git -C $GIT_ROOT ls-files --full-name --cached {include,src}/**/*.{hpp,cpp,tpp,h,c}外壳将--cached部件后的glob字符串扩展到file1..fileN,具体取决于与glob定义匹配的文件数,即
git -C $GIT_ROOT ls-files --full-name --cached file1 file2 ... fileN但是,当您的glob字符串被引用(从变量展开)时,同样的情况不会发生,它被展开为
git -C $GIT_ROOT ls-files --full-name --cached '{include,src}/**/*.{hpp,cpp,tpp,h,c}'这是你的球根线没有展开。
建议的方法是使用数组来展开glob定义的结果,以生成文件名,并将引用的数组展开作为参数传递。将代码更改为下面。
SRC_PATTERNS=({include,src}/**/*.{hpp,cpp,tpp,h,c})现在,数组已经存储了与您的glob定义相匹配的文件列表,我们只需将其传递给下面的命令即可。${arr[@]}是一个引号数组扩展,以确保文件名中的shell-meta字符不会导致名称被拆分。
git -C "${GIT_ROOT}" ls-files --full-name --cached "${SRC_PATTERNS[@]}"始终使用引号来展开shell变量(除非您看到有很好的理由不这样做,这在大多数情况下是否定的),并且在文件名中使用小写变量名而不使用_。
https://stackoverflow.com/questions/56734145
复制相似问题