检查命令是否在CMD内部

时间:2012-11-02 18:39:16

标签: windows batch-file cmd

我有一个命令的名字,我需要检查这个命令是否是内部的。如何在批处理脚本中执行此操作?

2 个答案:

答案 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)

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