检查CMD命令是否为内部命令

5
我有一个命令的名称,我需要检查这个命令是否是内部命令。在批处理脚本中该如何实现?

1
查看文档? :P 说真的,CMD 命令并没有太大变化。如果在一个版本中是内置命令,那么在后续版本中也会是内置命令。 - cHao
我忘了问一个问题,那就是为什么?你为什么需要这个?也许有更好的解决方法。 - kichik
2个回答

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


如果路径中实际上有一个名为 path 的程序,则 where path 报告错误。 - cHao
Windows 7 SP1。步骤1. 运行“SET PATH =”。 (OK) 步骤2。 HELP FIND ->“'help'不是内部或外部命令,也不是可运行的程序或批处理文件。” (哎呀...) - Andriy M
这就是为什么你必须运行%WINDIR%\system32\HELP而不是只运行HELP的原因。 - kichik
啊,我的错,没注意到,抱歉。(太神奇了,我在看什么?) - Andriy M
抱歉,是 find /? 返回了 9009。所以,是的,这是一种稍微不同的方法(没有使用 help),但基本思路仍然有效(我想)。 - Andriy M
显示剩余5条评论

3

kichik提供了一个很好的答案。但是,如果当前目录中恰好有与提供的命令名称匹配的可执行文件或批处理脚本,则可能会出现误报。

我所能想到的避免这个问题的唯一方法是在%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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接