【问题标题】:Batch (.bat): get the name of the first script, not the current one批处理(.bat):获取第一个脚本的名称,而不是当前的
【发布时间】:2012-04-10 11:24:46
【问题描述】:

我有first.batsecond.bat

first.bat 是:call second.bat

第二个是:echo %~n0(显示正在执行的批处理的文件名)

输出是Second.bat,但我希望它显示调用者文件名,而不是它自己的。

这可能吗?

【问题讨论】:

  • 你能接受最受好评的答案吗?我的不正确

标签: batch-file


【解决方案1】:

此批处理检测调用者脚本的名称,或者即使它是直接从命令行调用的

@echo off
setlocal DisableDelayedExpansion
set "func=%~0"
for /F "delims=\" %%X in ("%func:*\=%") do set "func=%%X"
if ":" == "%func:~0,1%" (
    goto %func%
)
REM *** Get the name of the caller
(
    (goto) 2>nul
    setlocal DisableDelayedExpansion
    call set "caller=%%~f0"
    call set _caller=%%caller:*%%~f0=%%
    if defined _caller (
        set "callType=batch"
        call "%~d0\:mainFunc\..%~pnx0" %*
    ) ELSE (
        set "callType=cmd-line"
        cmd /c "call "%~d0\:mainFunc\..%~pnx0" %*"
    )
    endlocal
)
echo NEVER REACHED
exit /b

:mainFunc
echo :mainFunc of %~nx0 arg1=%1 is called from '%caller%'/%callType%
exit /b

它使用了一个事实,即(goto) 语句将从堆栈中删除一层。
这将导致离开当前的批处理文件,%~f0 将是调用者脚本的名称(以及 %~0 该批处理的当前函数)或文本 %~f0(在从命令行调用的情况下)。

然后用"%~d0\:mainFunc\..%~pnx0"再次调用自己的脚本

外部脚本

为了方便使用,您可以添加一个帮助批处理文件。
用这一行在你自己的脚本中使用它

@echo off
<:GetCaller <nul call GetCaller.bat myCallerVar
echo This batch was called from "%myCallerVar%"

将帮助程序批处理文件命名为 GetCaller.bat

@echo off
setlocal DisableDelayedExpansion
set "func=%~0"
for /F "delims=\" %%X in ("%func:*\=%") do set "func=%%X"
if ":" == "%func:~0,1%" (
    goto %func%
)

REM *** STEP1
REM *** Get the filename of the caller of this script, needed for later restart that
(
    (goto) 2>nul
    setlocal DisableDelayedExpansion %= it could be reenabled by the GOTO =%
    set "_returnVar=%~1"
    call set "_lastCaller=%%~f0"
    call set "_argToLastCaller=%%*"
    call "%~d0\:Step2\..%~pnx0" %*
)
exit /b %= This is never reached =%

:Step2
REM *** STEP2
REM *** Get the filename/cmd-line of the caller of the script
(
    (goto) 2>nul
    (goto) 2>nul
    setlocal DisableDelayedExpansion %= it could be reenabled by the GOTO =%    
    set "_returnVar=%_returnVar%"
    set "_lastCaller=%_lastCaller%"
    set "_argToLastCaller=%_argToLastCaller%"
    call set "caller=%%~f0"
    call set _caller=%%caller:*%%~f0=%%
    if defined _caller (
        set "callType=batch"
        call "%~d0\:Step3batch\..%~pnx0"
    ) ELSE (
        set "callType=cmd-line"
        cmd /c "call "%~d0\:Step3batch\..%~pnx0" "
    )
    endlocal
)
exit /b %= This is never reached =%

:Step3batch
REM *** STEP3 Restart the requester batch, but jump to the label :GetCaller
call :GetCaller
exit /b %= This is never reached =%

:GetCaller
REM *** This uses the trick, that starting a batch without CALL will jump to the last used label
if "%_returnVar%" NEQ "" set "%_returnVar%=%_caller%"
%_lastCaller% %_argToLastCaller%

echo #6 never reached

【讨论】:

  • 将其简化为只有 2 或 3 行嵌入到其他脚本中......目标只是检测调用脚本名称......你能举个例子 os 只是果汁(获取调用者脚本的名称)...
  • @ZEE 2 或 3 行是不可能的,因为您必须退出当前批处理以获取调用者脚本名称,然后您必须重新启动当前脚本,但要避免无限循环。但是可以将完整的代码移动到帮助程序批处理文件中。
  • @ZEE 添加了帮助脚本
【解决方案2】:

我认为最简单的方法是将第一批的文件名作为参数传递给第二批,像这样。

REM First.bat
call Second.bat %~n0

REM Second.bat
echo %1

希望这会有所帮助!

【讨论】:

    【解决方案3】:

    在调用second.bat之前将%~n0的值存储在环境变量中

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-10-09
      • 1970-01-01
      • 2011-10-15
      • 2017-09-09
      • 2017-08-22
      • 2011-05-08
      相关资源
      最近更新 更多