我有这个简单的脚本可以自动化git status
许多 git 存储库:
@ECHO OFF
for /D %%s in (C:\Projects\*) do (
set HasChangesCommand=git -C %%s status --porcelain | findstr . && echo 1 || echo 0
set IsAheadCommand=git -C %%s status --porcelain | findstr ahead && echo 1 || echo 0
set IsDiveregedCommand=git -C %%s status --porcelain | findstr diverged && echo 1 || echo 0
if "%HasChangesCommand%" == "1" (
call Info %%s;
git -C %%s status --porcelain
echo.
) else if "%IsAheadCommand%" == "1" (
call Warning Push %%s
) else if "%IsDiveregedCommand%" == "1" (
call Warning Sync %%s
)
call Info %HasChanges%
)
基本上,我想分析每个目录的输出git status
,并根据输出显示更简单的消息。
但它不起作用。
我猜我在运行块命令时遇到了问题if else
。
我做错了什么?
答案1
你至少有两个问题:
Cmd.exe 的工作方式是,整个中的所有变量
do ( ... )
都会被扩展立刻,就像它只是一个单行命令一样——实际上每次迭代都不会重复扩展。这意味着使用所做的任何更改set
都不会产生任何效果。您需要使用延迟扩展
!var!
或将循环重写为call
:子例程而不是直接(...)
块。(更好的是,用 PowerShell 或 Bash 或其他没有此问题的语言重写脚本。)
你没有把“git”命令的输出放在变量中——而是把命令他们自己在变量中。例如,
"%HasChangesCommand%:
包含文字文本"git -C project1 status..."
,当然它永远不会与相等"0"
。要将命令的输出捕获到变量中,您需要
for /f
在 Cmd 或$(…)
Sh/Bash shell 中使用。例如:Cmd: for /f "tokens=*" %%a in ('git -C project1 status') do set HasChangesResult=%%a Bash: HasChangesResult=$(git -C project1 status && echo 0 || echo 1)
但在这种情况下,您实际上不需要输出,因为您可以直接通过
%ERRORLEVEL%
Cmd(或类似地$?
在 Bash 中)获取退出状态:Cmd: git -C project1 status set HasChangesResult=%ERRORLEVEL% Bash: git -C project1 status HasChangesResult=$?
与上一个问题相关,即使像 这样的操作符
||
与 在同一行中使用,它们仍被视为操作符set=
- 它们实际上不会成为值的一部分。例如,此命令:set HasChangesCommand=git -C %%s status --porcelain | findstr . && echo 1 || echo 0
可以(在心理上)分为:
(set HasChangesCommand=git -C %%s status --porcelain | findstr .) && echo 1 || echo 0
换句话说,由于
set
命令成功执行,因此调用 echo。