0

我们当前的构建系统是从“主”批处理文件调用的大量批处理文件。如何找到从“主”批处理文件中调用的所有批处理文件?

不幸的是,存储库还包含许多其他批处理文件,我不能只列出工作副本中的所有批处理文件。

我不太关心“模拟”真正的执行。如果我得到一个可能从主批处理文件中调用的所有文件的列表,那就太好了。

有 299 个文件,所以我不想在每个文件中添加一个 echo ""。

引用的批处理文件使用“call xyz.bat”调用,即相对路径。有时批处理文件会更改当前工作目录,如下所示:

cd client
call mk.bat
cd ..

或者

pushd client\install
call prepare.bat
popd

编辑:添加示例

4

2 回答 2

2

糟糕——这个问题几乎不可能完美解决,原因如下:

1)批处理文件可能被多种机制“调用”:

  • CALL scriptName

  • 管道,例如:scriptName | findstr ...

  • FOR /F,例如:for /f ... in ('scriptName ...') do ...

  • CMD,例如:cmd /c scriptName ...%comspec% /c scriptName

  • 开始,例如start "" scriptName ...

2) 上述任何构造都可能存在,而不是对批处理脚本的“调用”。例如,CALL 可用于调用标签或执行命令。FOR /F 可用于解析字符串。等等

3)无论使用哪种“调用”机制,“调用”目标都可以用变量而不是字符串字面量来表示。例如:

set "myScript=ScriptName"
REM the SET may not be anywhere near the CALL
call %myScript%

4) 脚本名称和路径可能不会出现在代码中。它可以从文件系统中动态读取,也可以通过逻辑导出。

5) 实际调用本身可以作为值嵌入到变量中。这适用于任何调用机制。例如:

set "myCommand=CALL"
%myCommand% ScriptName

6)正如您在问题中指出的那样,脚本的路径可能是相对的,并且脚本可能会更改当前目录。或者“调用”可能依赖于 PATH 环境变量。

7) 任何“被调用”的脚本本身都可以“调用”另一个脚本。


您可以使用 FINDSTR 查找任何调用机制,并且您可能会找到大多数“调用”。但可能会有很多误报。您可以添加/N开关以在每个匹配的行前面加上行号。然后,您需要在文本编辑器中手动检查每个匹配行,看看它是否是您感兴趣的“调用”。

findstr /nir /c:"\<call\>" /c:"|" /c:"for  */f " /c:"\<cmd\>" /c:"\<%comspec%\>" /c:"\<start\>" *.bat

可能有很多误报,您最好手动跟踪整个脚本的逻辑:-(尤其如此,因为不能保证 FINDSTR 会找到所有“调用”,因为调用本身可能会被隐藏在后面一个变量。

于 2013-02-15T12:19:32.193 回答
1

您可以预先记录每个批处理文件。我知道你说过你不愿意,但这并不像你想象的那么难。

@echo off
:: addlogging.bat patch|unpatch
::
:: addlogging.bat patch
::    finds every .bat file in the current directory and every subdir
::    beyond, and patches each, prepending an echo to a log file
::
:: addlogging.bat unpatch
::    finds every .bat file in the current directory and every subdir
::    beyond, and removes the logging patch

setlocal

if #%1==#patch goto next
if #%1==#unpatch goto next
goto usage

:next
for /f "delims=" %%I in ('dir /s /b *.bat') do (
    if not "%%I"=="%~f0" (
        if #%1==#patch (
            set /p I="Patching %%I... "<NUL
            echo @echo %%time%% %%~f0 %%* ^>^> "%%userprofile%%\Desktop\%%date:/=-%%.log">"%%~dpnI.tmp"
        ) else (
            set /p I="Unpatching %%I... "<NUL
        )
        findstr /v "^@echo.*time.*~f0.*>>" "%%I">>"%%~dpnI.tmp"
        move /y "%%~dpnI.tmp" "%%I">NUL
        echo Done.
    )
)
goto :EOF

:usage
echo usage: %~nx0 patch^|unpatch
于 2013-02-15T14:35:52.670 回答