windows “X未被识别为内部或外部命令、可操作程序或批处理文件”的原因是什么?

wlwcrazw  于 2022-12-24  发布在  Windows
关注(0)|答案(3)|浏览(278)

我有一个单行代码段,它在命令行中工作得很好,但是当我将它作为批处理脚本的一部分运行时,它会失败并抛出错误。
以下命令的行为符合预期,删除文件夹中的所有空子文件夹。

for /f "delims=" %d in ('dir /s /b /ad ^| sort /r') do rd "%d"

但是,当像这样放入批处理文件时...

FOR /f "delims=" %%d in ('dir /s /b /ad ^| sort /r') do rd "%%d"

......它会抛出标准误差:
排序不被识别为内部或外部命令
在过去的一个小时左右的时间里,我一直在尝试是否转义管道,改变选项的顺序,查找dirsort的文档,等等,但我仍然无法弄清楚这里发生了什么,批处理文件的其余部分,只有几行,工作正常,这是其中唯一失败的一行。

t98cgbkg

t98cgbkg1#

A)Windows命令处理程序如何搜索命令?

Windows命令处理器搜索要执行的 * COMMAND *,
1.不是cmd.exe的内部命令
1.仅指定了文件名,而没有文件扩展名和路径
对于与模式command.*匹配且具有本地环境变量PATHEXT中列出的文件扩展名的文件
1.当前目录中的第一个
1.其次是本地环境变量PATH的所有目录。

    • SORTFINDFINDSTRROBOCOPYXCOPY**以及更多命令不是cmd.exe的内部命令。它们是随Windows安装的控制台应用程序,位于目录%SystemRoot%\System32中,文件名为sort.exefind.exefindstr.exerobocopy.exexcopy.exe ...

Windows上默认提供的此类控制台应用程序称为外部命令,以便更好地与未随Windows操作系统安装的控制台应用程序区分开来。

B)如何定义环境变量PATH?

PATH变量有三种类型:
1.* * System**PATH,用于所有帐户并存储在Windows注册表中的以下项下:

HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\Environment

1.* * 用户**PATH,仅用于当前帐户,存储在Windows注册表中的以下项下:

HKEY_CURRENT_USER\Environment

1.* * 本地**PATH始终是启动当前进程的父进程的本地PATH副本
对于用作Windows桌面的Windows资源管理器示例,Windows将systemuserPATH连接到localPATH,桌面屏幕上的快捷方式以及Windows开始菜单和Windows任务栏作为用户的可视界面,称为Windows shell,用户通常从该界面启动程序。
在启动新进程时,Windows为新进程复制正在运行进程的整个当前活动环境变量列表。Windows内核库函数CreateProcess根据函数参数lpEnvironment将此环境变量列表从当前进程的内存复制到新进程的内存(指向环境的长指针)为空指针。CreateProcess函数之一总是在Windows上从另一个可执行文件启动一个可执行文件时使用。
父进程不能修改任何子进程的环境变量,子进程也不能修改其父进程的环境变量。
这意味着一旦像cmd.exe这样的进程被启动来执行批处理文件,该进程就有了自己的环境变量集,只有进程本身可以修改,其他进程不能修改已经运行的进程的环境变量。

C)错误消息是什么意思?

错误消息
'...'未被识别为内部或外部命令,
可操作程序或批处理文件。
总是意味着

  • 的文件名
  • 控制台应用程序
  • GUI应用程序
  • 脚本(批处理文件、PowerShell脚本、Perl脚本、VBScript、JScript等)

已指定执行,很可能没有文件扩展名和可执行文件/脚本文件的(完整)路径

  • Windows在当前目录或当前活动环境变量PATH的任何其他目录中找不到与模式FileName.*匹配且文件扩展名列在当前活动环境变量PATHEXT中的文件。

D)出现此错误消息的可能原因是什么?

典型的原因是:

    • 1.由于键入错误,指定的要执行文件的文件名有误。**

逐字符检查命令/可执行文件的名称。

    • 2.当前目录与包含要执行的文件的目录不同。**

在命令行上运行echo Current directory is: %CD%或将此行添加到命令行上方的批处理文件中,无法查看当前目录。

    • 3.根本没有安装要运行的可执行文件或脚本。**

验证要运行的可执行文件是否存在。一些安装包只有在之前安装了其他包(如Java、NPM、PHP等)的情况下才能工作。

    • 4.要执行的文件的目录根本不在**PATH中。

在Windows控制面板中打开系统设置窗口,单击左侧的高级系统设置,单击按钮环境变量并在两个列表中查找Path及其值。默认情况下,Path仅存在于系统变量列表中。

    • 5.修改系统或用户**PATH后,未重新启动正在运行的进程/应用程序。

用户或安装程序使用命令setx或通过控制面板-系统和安全-系统-高级系统设置-环境变量修改了系统PATH用户PATH,但已运行的进程/应用程序(如打开的命令提示符或PowerShell窗口)未关闭/退出和打开/修改PATH后重新启动。这是必要的,详见以下章节F)

    • 6.在64位Windows上找不到%SystemRoot%\System32中的可执行文件。**

在处理器也支持x86指令集的64位Windows上,%SystemRoot%\System32目录包含64位可执行文件,%SystemRoot%\SysWOW64目录包含32位可执行文件。大多数可执行文件都存在于这两个目录中。但也有一些可执行文件仅存在于System32中,少数仅存在于SysWOW64中。
默认情况下,systemPATH包含第一个文件夹路径%SystemRoot%\System32。但是,在两个Windows系统文件夹中的哪一个中搜索指定的可执行文件(不带路径或带路径%SystemRoot%\System32)取决于执行环境。在64位环境中执行的应用程序或脚本实际上访问的是%SystemRoot%\System32,而在32位环境中执行的应用程序或脚本实际上访问的是%SystemRoot%\System32。位环境被Windows file system redirector重定向到目录%SystemRoot%\SysWOW64
在32位环境中运行的应用程序或脚本要在%SystemRoot%\System32中运行64位可执行文件,必须使用文件路径为%SystemRoot%\Sysnative的可执行文件的完全限定文件名。

    • 注意:**%SystemRoot%\Sysnative既不是目录,也不是任何类型的链接。它是一种非常特殊的东西,只存在于x86应用程序中。它不存在于amd64应用程序中。批处理文件中的条件if exist %SystemRoot%\Sysnative在两种环境中始终为false,但if exist %SystemRoot%\Sysnative\cmd.exe在32位执行环境中为true,在64位环境和32位Windows中为false。此条件可用于批处理脚本中,以确定批处理文件是否由64位Windows上%SystemRoot%\SysWOW64中的32位cmd.exe处理。根据任务,了解此条件可能很重要。

另请参阅Microsoft文档WOW64 Implementation DetailsRegistry Keys Affected by WOW64

    • 7.**PATH包含对尚未定义的环境变量的引用。

可以在PATH中使用对另一个环境变量(如SystemRoot)的值的引用来指定文件夹路径。重要的是,此环境变量也在同一组环境变量或Windows首先处理的一组环境变量中定义。
例如,如果将%JAVA_HOME%\bin添加到systemPATH环境变量中,还必须定义一个system环境变量JAVA_HOME,其中包含Java程序文件的基本文件夹路径。仅定义user环境变量JAVA_HOME或稍后在local中定义环境变量JAVA_HOME是不够的批处理文件的环境。
如果将环境变量JAVA_HOME定义为systemuser环境变量,但未在Windows命令进程的local环境中稍后定义的JAVA_HOME上定义,则添加到user%JAVA_HOME%\bin将由Windows展开为完全限定的文件夹路径。
在Windows开始菜单中对systemuserPATH进行修改后打开一个新的command prompt窗口,运行set path,输出PATH不应再包含任何%Variable%环境变量值引用。

      1. LOCAL变量**PATH以前在命令行或批处理文件中修改过。

在命令行上运行set path或将此命令添加到命令行上方的批处理文件中,无法查看环境变量PATHPATHEXT的当前值。
最后一个原因是在执行包含set path=...以上某处的批处理文件时未找到外部命令SORT

E)如何避免此错误消息?

最好是编写一个批处理文件,使其独立于PATHPATHEXT以及PATH中的目录顺序,这意味着这里使用命令行:

FOR /f "delims=" %%d in ('dir /s /b /ad ^| %SystemRoot%\System32\sort.exe /r') do rd "%%d"

任何可执行文件存储在%SystemRoot%\System32中的外部命令都应在具有此路径和文件扩展名.exe的批处理文件中指定。这样,Windows命令解释程序就不需要使用localPATHPATHEXT搜索文件,并且批处理文件始终有效(只要环境变量SystemRoot不在批处理文件中修改,我从未见过)。

F)系统或用户PATH更改何时应用于进程?

当用户通过Windows开始菜单或从Windows资源管理器窗口打开命令提示符窗口时,用户使用选项/K隐式启动cmd.exe,以在完成命令后保持控制台窗口打开,这有利于调试批处理文件。
在Windows资源管理器中双击批处理文件时,用户启动cmd.exe处理批处理文件,并隐式使用选项/C在批处理完成后关闭控制台窗口,这不利于调试批处理文件,因为在这种情况下看不到错误消息。
在这两种情况下,Windows都会创建启动cmd.exe的应用程序(通常是Windows资源管理器)的环境变量副本。因此,启动的命令进程具有localPATH,其值与启动cmd.exe时的父进程相同。
示例:
1.打开命令提示符窗口,运行title Process1set path

输出为PATHPATHEXT,与当前在窗口标题为 * Process 1 * 的控制台窗口中为当前用户帐户定义的一样。
1.运行set PATH=%SystemRoot%\System32,然后再次运行set path
输出仍然是PATHPATHEXT,但PATH现在只包含一个目录。
1.运行start "Process2"并在窗口标题为 * Process 2 * 的新控制台窗口中运行命令set path
输出为PATHPATHEXT,其值与之前 * 过程1 * 中的值相同。
这表明在启动新进程时,正在运行的进程的当前环境变量被复制,而不是Windows本身当前存储在Windows注册表中的变量。
1.在 * 进程2 * 中运行命令set PATH=和下一个命令set path
输出仅为PATHEXT,因为localPATH对于 * Process 2 * 不再存在。
这说明每个进程都可以修改其环境变量,包括完全删除。
1.切换到 * Process 1 * 窗口,运行命令set PATH=%PATH%;%SystemRoot%,然后运行set path
输出为PATH(包含两个目录)和PATHEXT
1.运行命令start "Process3",并在标题为 * Process 3 * 的打开窗口中运行命令set path
输出为PATH,具有两个目录,这两个目录也是为 * Process 1 * 和PATHEXT定义的。
1.在 * 进程3 * 中运行命令set PATH=%SystemRoot%\System32
%SystemRoot%扩展为C:\Windows时,有3个命令进程正在运行,localPATH的值如下:

  • 进程1 *:PATH=C:\Windows\System32;C:\Windows
  • 进程2 *:PATH根本不存在。
  • 进程3 *:PATH=C:\Windows\System32

那么,打开控制面板-系统-高级系统设置-环境变量并将值为C:\Temp环境变量PATH添加到用户变量列表中,或者在已经存在用户PATH环境变量的情况下,会发生什么情况?编辑PATH并将;C:\Temp附加到该值?
只要打开显示两个列表的标题为环境变量的对话框窗口,修改变量时不会发生任何事情,直到单击按钮确定将所有更改接管到Windows注册表并关闭窗口。
我们回到三个正在运行的命令进程,分别在 * Process 1 Process 2 * 和 * Process 3 * 中运行命令set path,可以看到:

  • 进程1 *:PATH=C:\Windows\System32;C:\Windows
  • 进程2 *:PATH根本不存在。
  • 进程3 *:PATH=C:\Windows\System32

已在运行的进程上没有任何更改。

任何进程都不能修改不同运行进程的环境变量!

从Windows开始菜单打开另一个命令提示符窗口,并在第四个命令进程中运行命令set path。可以看到,第四个命令进程的localPATH现在已附加目录C:\Temp
然后关闭所有四个命令进程并删除添加的userPATH,如果之前附加了此目录路径,则从userPATH中删除;C:\Temp
如果没有进程可以修改已经运行的进程的环境变量,这怎么可能呢?
使用按钮确定关闭环境变量窗口时,如何修改作为Windows桌面运行的Windows资源管理器示例的环境变量列表?
eryksun在他的评论中给出了这两个问题的答案。
单击环境变量窗口的按钮确定,将对系统用户变量的修改写入注册表后,Windows向所有顶层窗口发送WM_SETTINGCHANGE消息,以通知正在运行的应用程序系统参数已更改。
这取决于应用程序是否处理此事件消息以及如何处理。Windows桌面运行的Windows资源管理器从注册表中读取环境变量并相应地更新其环境变量列表。其他应用程序如Total Commander也处理此消息并更新其环境变量列表。但幸运的是cmd.exe没有这样做,因为这将是真正的问题。
是否可以在命令提示符窗口或批处理文件中通过WM_SETTINGCHANGE通知修改systemuser变量?
可以使用reg add命令修改环境变量的注册表值。但这不会导致向所有顶级窗口发送WM_SETTINGCHANGE消息。使用reg addregedit进行的此类更改需要重新启动Windows(或至少注销并登录当前用户)才能考虑在内。
但是还有一个命令setx,它是为修改systemuser变量而设计的,并且在注册表根据指定的参数更新后,它也会向所有顶级窗口发送WM_SETTINGCHANGE消息。在命令提示符窗口中运行setx /?以了解详细信息。但是请注意,setx不修改正在运行的命令进程的本地环境变量。这必须使用除setx之外使用的命令set来完成。

G)Windows如何处理环境变量PATHEXT?

与环境变量PATH相比,Windows对带有文件扩展名列表的环境变量PATHEXT的处理方式不同。

系统PATHEXT用户PATHEXT连接到本地PATHEXT
用户PATHEXT替换*系统**PATHEXT中在已定义用户PATHEXT的帐户环境下运行的所有进程。

默认情况下,仅定义了一个systemPATHEXT环境变量。

H)是否可以禁用当前目录中的文件搜索?

如果在命令行或批处理文件中指定了脚本文件或可执行文件的文件名,而没有任何路径,这意味着参数字符串中没有反斜杠\(或正斜杠/,因为自动更正),则Windows命令处理器默认在当前目录中搜索。
但是在Windows Vista和更高的Windows客户端版本上以及在Windows Server 2003和更高的Windows服务器版本上,确实有可能通过定义具有任何值的环境变量NoDefaultCurrentDirectoryInExePath来禁止在当前目录中搜索脚本/可执行文件,所述值由eryksun在其下面的注解中写入,并由Microsoft“s关于函数NeedCurrentDirectoryForExePathA的文档。
有关此环境变量用法的更多详细信息,请参见Removing the current working directory from the path

I)如何修改系统或用户路径?

用户最好使用Windows GUI对话框窗口环境变量修改systemuserPATH环境变量。此对话框窗口可按如下方式打开:
1.单击Windows开始菜单按钮。
1.在键盘上键入环境变量
1.有提供的Windows的两个项目:

编辑系统环境变量
编辑帐户的环境变量

1.单击两个项目中的一个以打开"环境变量“窗口。
也可以打开Windows控制面板。接下来必须单击系统和安全性,并为显示选项 * 查看方式 * 选择 * 类别 *。接下来必须单击系统。必须单击左侧的高级系统设置,然后单击按钮环境变量...
如果键盘上有Pause键或至少有与Fn键的组合键,也可以通过按Windows徽标键+ Pause组合键打开系统窗口。另请参阅Microsoft文档页Keyboard shortcuts in Windows
进一步的用户操作是自解释的,用于编辑上部列表中的userPath或下部列表中的systemPath

xytpbqjk

xytpbqjk2#

很有可能是您在修改PATH变量,或者是在脚本的其他地方覆盖了它。由于sort是一个外部命令,而不是命令行中的其他命令,如fordirrd,这些命令都是cmd内部命令。需要PATH变量来查找命令。如果未定义PATH,则仅在当前工作目录中搜索外部命令。还需要PATHEXT变量来定义可执行文件的标准文件扩展名,如.com.exe。因此,当sort出现在命令提示符或批处理文件中时,系统将在当前工作目录和PATH变量指定的所有目录中搜索基本名称为sort且扩展名为PATHEXT的文件。命令sort实际上称为sort.exe,通常位于C:\Windows\System32中。

djmepvbi

djmepvbi3#

在我的例子中,我非常确定我没有弄乱PATH,我没有意识到pathPATH是相同的,CMD不区分大小写。

相关问题