我正在编写一个 Bash 脚本,用于检查两个 git 提交之间的差异,并将其与 glob 模式列表交叉引用,以查看与这些 glob 模式匹配的任何内容是否已更改。
我遇到了这样的限制:只有在按字面定义 glob 时才匹配 glob,而不是从变量读取 glob。
这是我到目前为止所拥有的:
function files_changed() {
local latter_commit=$1
local former_commit=$2
local files=("${@:3}")
for file in $(git diff --name-only "$former_commit" "$latter_commit"); do
echo "Checking file $file"
for pattern in "${files[@]}"; do
if [[ "$file" == $pattern ]]; then
echo "File $file changed, matched by pattern $pattern"
return 0
else
echo "File $file did not match pattern $pattern"
fi
done
done
echo "No files changed"
return 1
}
但这不起作用:
array=("migrations/*.up.sql")
files_changed HEAD HEAD~1 ${array[@]}
输出:
Checking file migrations/20240000000001_migration.up.sql
File migrations/20240000000001_migration.up.sql did not match pattern migrations/*.up.sql
如果我从字面上比较字符串,我确实看到了我想要的行为:
> if [[ "migrations/20240000000001_migration.up.sql" == migrations/*.up.sql ]]; then echo "Match"; else echo "No Match"; fi
Match
但如果我将它们分配给变量则不会:
> X=migrations/20240000000001_migration.up.sql; Y=migrations/*.up.sql; if [[ "$X" == $Y ]]; then echo "Match"; else echo "No Match"; fi
No Match
我可以在网上找到的解决方法都取决于扩展全局模式,但这不适合我的用例,因为与更改列表匹配的文件可能不存在于我当前的文件系统中。
如何才能正确评估此比较?
正如 @LeGEC 指出的那样,git diff 允许通过 glob 进行过滤:
function files_changed() {
local latter_commit=$1
local former_commit=$2
local -a patterns=$3
for file in $(git diff --name-only "$former_commit" "$latter_commit" -- "${patterns[@]}"); do
echo "File $file changed, matched by patterns ${patterns[*]}"
return 0
done
echo "No files changed"
return 1
}
至于我看到的奇怪行为,那只是因为我从一个包含 bash shebang 的文件复制到运行 zsh 的 shell 中。