我有一个命令的名字,我需要检查这个命令是否是内部的。如何在批处理脚本中执行此操作?
答案 0 :(得分:8)
经过大量调整后,感谢@Andriy M的帮助,它终于有效了。
@ECHO off
CALL :isInternalCommand dir dirInternal
ECHO is dir internal: %dirInternal%
CALL :isInternalCommand find findInternal
ECHO is find internal: %findInternal%
exit /b 0
:isInternalCommand
SETLOCAL
MKDIR %TEMP%\EMPTY_DIR_FOR_TEST > NUL 2>& 1
CD /D %TEMP%\EMPTY_DIR_FOR_TEST
SET PATH=
%~1 /? > NUL 2>&1
IF ERRORLEVEL 9009 (ENDLOCAL
SET "%~2=no"
) ELSE (ENDLOCAL
SET "%~2=yes"
)
GOTO :EOF
您可以使用where
。如果失败,该命令可能是内部的。如果成功,您将获得证明它不是内部的可执行路径。
C:\Users\user>where path
INFO: Could not find files for the given pattern(s).
C:\Users\user>where find
C:\Windows\System32\find.exe
编辑:正如评论所示,如果您正在寻找可移植性而不仅仅是研究,这可能不是最佳解决方案。所以这是另一种可能的解决方案。
将%PATH%
设置为空,以便HELP
无法找到任何内容,然后对您要检查的命令运行HELP
。
C:\Users\user>set PATH=
C:\Users\user>path
PATH=(null)
C:\Users\user>%WINDIR%\System32\help del
Deletes one or more files.
DEL [/P] [/F] [/S] [/Q] [/A[[:]attributes]] names
[...]
C:\Users\user>%WINDIR%\System32\help find
'find' is not recognized as an internal or external command,
operable program or batch file.
如果命令没有帮助,这可能仍会失败。
编辑2:没关系,这也行不通。两种情况都返回%ERRORLEVEL%=1
。
答案 1 :(得分:3)
我能想到避免该问题的唯一方法是在%TEMP%
目录中创建一个已知为空的文件夹,然后从该文件夹运行测试。
以下是kichik解决方案的修改版本,应该可以使用。
@echo off
setlocal
::Print the result to the screen
call :isInternal find
call :isInternal dir
::Save the result to a variable
call :isInternal find resultFind
call :isInternal dir resultDir
set result
exit /b
:isInternal command [rtnVar]
setlocal
set "empty=%temp%\empty%random%"
md "%empty%"
pushd "%empty%"
set path=
>nul 2>nul %1 /?
if errorlevel 9009 (set rtn=not internal) else (set rtn=internal)
popd
rd "%empty%"
(
endlocal
if "%~2" neq "" (set %~2=%rtn%) else echo %1 is %rtn%
)
exit /b 0
这是一个简单列出所有内部命令的脚本,假设HELP包含完整的内部命令列表。
更新: FOR和IF都有特殊的解析规则,可以防止这些命令在通过FOR变量或延迟扩展执行时起作用。我不得不重写这个脚本以使用CALL并通过CALL参数执行命令。
@echo off
setlocal enableDelayedExpansion
set "empty=%temp%\empty%random%"
md "%empty%"
pushd "%empty%"
for /f "delims= " %%A in ('help^|findstr /rc:"^[^ ][^ ]* "') do call :test %%A
popd
rd "%empty%"
exit /b
:test
setlocal
set path=
%1 /? >nul 2>nul
if not errorlevel 9009 echo %1
exit /b 0