4

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

4

2 回答 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

于 2012-11-02T18:45:43.950 回答
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
于 2012-11-03T01:37:07.917 回答