“…”是什么原因不被识别为内部或外部命令,可操作程序或batch file?

我有一个在命令行中完美工作的单行代码片段,但是当我将它作为批处理脚本的一部分运行时会失败并引发错误。

下面的命令按预期行为,删除文件夹中的所有空子文件夹。

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

然而,当把这样的batch file…

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

它会抛出标准错误: Sort is not recognised as an internal or external command...

我一直在做最后一个小时左右的试验,有没有逃脱pipe道,改变选项的顺序,查找dirdir的文件等,但我仍然无法弄清楚是什么去这里 batch file的其余部分,只有几行,工作正常,这是唯一的行失败。

谁能帮忙? 在此先感谢,我真的很感激。

A)Windows命令解释器如何search命令?

Windows命令解释器search命令来执行哪个

  1. 不是cmd.exe的内部命令
  2. 只是用没有文件扩展名和没有path的文件名指定的

匹配模式command.*的文件, 在本地环境variablesPATHEXT列出文件扩展名

  1. 首先在当前目录中
  2. 接下来在本地环境variablesPATH所有目录中。

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

Windows上默认可用的这种控制台应用程序称为外部命令,以便将其与未安装Windows操作系统的控制台应用程序区分开来。


B)如何定义环境variablesPATH?

有三种types的PATHvariables:

  1. 用于所有帐户并存储在Windowsregistry项下的系统 PATH

     HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\Environment 
  2. 用户 PATH只用于当前帐户并存储在Windowsregistry项下:

     HKEY_CURRENT_USER\Environment 
  3. 本地 PATH ,它始终是启动当前进程的父进程的本地PATH副本

Windows将用于Windows桌面的Windows资源pipe理器实例的系统用户 PATH连接到本地 PATH ,桌面屏幕上的快捷方式和Windows开始菜单作为用户的可见界面。

在启动一个新进程时,运行进程的整个当前活动的环境variables表被复制到Windows的新进程中。

父进程不能修改任何subprocess的环境variables,subprocess也不能修改其父进程的环境variables。

这意味着一旦像cmd.exe这样的进程开始执行batch file,进程就拥有自己的一组环境variables,只有进程本身才能修改。 没有其他进程可以修改已经运行的进程的环境variables。


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

错误消息

“…”不被识别为内部或外部命令,
可操作程序或batch file。

总是意味着

  1. a的文件名

    • 控制台程序
    • GUI应用程序
    • 脚本(batch file,PowerShell脚本,Perl脚本,VBScript,JScript,…)

    被指定执行,很可能没有文件扩展名,也没有(完整)path到可执行文件/脚本文件

  2. Windows无法find与当前活动环境variablesPATH中当前活动环境variablesPATHEXT中列出的文件扩展名或当前活动环境variablesPATH任何其他目录中匹配模式FileName.*的文件。


D)这个错误信息有什么可能的原因?

典型的原因是:

1.由于input错误,要执行的文件的文件名被指定为错误。

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

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

运行echo Current directory is: %CD%命令行上的echo Current directory is: %CD%或将此行添加到命令行上面的batch file中,该文件无法看到当前目录是什么。

3.要执行的文件的目录完全不在 PATH 中。

在Windows 控制面板中打开系统设置窗口,点击左侧的高级系统设置 ,点击环境variablesbutton,并查看Path及其值的两个列表。 默认情况下Path只存在于系统variables列表中。

4. 在命令行或batch file中修改 LOCALvariables PATH

在命令行上运行set path ,或将此命令添加到命令行上方的batch file中,该命令行无法看到环境variablesPATHPATHEXT的当前值。

最后的原因是负责外部命令SORT不被执行的batch file,其中包含上面set path=...以上的地方。


E)如何避免这个错误信息?

最好是编写一个独立的PATHPATHEXTbatch file和PATH的目录的顺序,这意味着在这里使用命令行:

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

其可执行文件存储在%SystemRoot%\System32任何外部命令都应在具有此path的batch file中指定,文件扩展名为.exe 。 然后,Windows命令解释器不需要使用本地 PATHPATHEXT来search文件,并且batch file始终工作(只要环境variablesSystemRoot在batch file中也没有被修改,这是我从未见过的)。


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

当用户通过Windows开始菜单或在Windows资源pipe理器窗口中打开命令提示符窗口时,用户使用选项/K以隐式方式启动cmd.exe ,以在完成用于debuggingbatch file的命令后保持控制台窗口打开。

当在Windows资源pipe理器中双击batch file时,用户启动cmd.exe以隐式处理batch file,使用选项/C在完成批处理后closures控制台窗口,这不利于debuggingbatch file,因为错误消息不能在这种情况下可以看到。

在这两种情况下,Windows都会创build应用程序的环境variables的副本,并启动通常为Windows资源pipe理器的cmd.exe 。 因此,启动的命令进程具有本地 PATH其值与父进程在启动cmd.exe的值相同。

例:

  1. 打开命令提示符窗口,运行title Process1并运行set path
    输出是当前在控制台窗口中为当前用户帐户定义的PATHPATHEXT ,现在具有窗口标题Process1

  2. 运行set PATH=%SystemRoot%\System32 ,然后再次set path
    输出再次是PATHPATHEXT ,但PATH只包含一个目录。

  3. 运行start "Process2"并在窗口标题Process2的新控制台窗口中运行命令set path
    输出是PATHPATHEXT ,与Process1中的值相同。
    这表明在启动一个新进程时,运行进程的当前环境variables被复制,而不是Windows本身当前存储在Windowsregistry中的内容。

  4. Process2中运行命令set PATH=和下一个set path
    输出只是PATHEXT因为Process2中不存在本地 PATH
    这表明每个进程都可以修改其环境variables,包括完全删除。

  5. 切换到Process1窗口,运行命令set PATH=%PATH%;%SystemRoot%和下一个set path
    输出是PATH与两个目录和PATHEXT

  6. 运行命令start "Process3"并在打开的窗口中用标题Process3命令set path
    输出是PATH ,同时也为Process1PATHEXT定义了两个目录。

  7. Process3中运行命令set PATH=%SystemRoot%\System32

%SystemRoot%扩展到C:\Windows时,有3个命令进程使用以下值作为本地 PATH运行:

Process1PATH=C:\Windows\System32;C:\Windows
Process2PATH根本不存在。
Process3PATH=C:\Windows\System32

那么现在打开控制面板 – 系统 – 高级系统设置 – 环境variables ,并向用户variables列表添加值为C:\Temp环境variablesPATH ,或者在已经有用户 PATH环境variables的情况下, 编辑 PATH并追加;C:\Temp的值?

那么,只要打开标题Environment Variables显示两个列表的对话窗口被打开,修改variables就不会发生任何事情,直到单击OKbutton接pipeWindowsregistry中的所有更改并closures窗口。

让我们回到3个运行命令进程,并在Process1Process2Process3中运行命令set path 。 可以被看见:

Process1PATH=C:\Windows\System32;C:\Windows
Process2PATH根本不存在。
Process3PATH=C:\Windows\System32

已经运行的进程没有任何改变。

没有进程可以修改正在运行的进程的环境variables。

从Windows开始菜单打开多一个命令提示符窗口,并在第四个命令中运行命令set path 。 可以看出,第四个命令进程的本地 PATH现在已经附加了目录C:\Temp

然后closures所有4个命令进程并删除添加的用户 PATH分别从用户 PATH删除;C:\Temp如果之前已经附加了这个目录path。

如果没有进程可以修改已经运行的进程的环境variables,这怎么可能?

在使用button确定closures环境variables窗口时,如何修改作为Windows桌面运行的Windows资源pipe理器实例的环境variables列表?

这两个问题的答案是由eryksun在他的评论中给出的。

在将系统用户variables的修改写入registry后,Windows 单击环境variables”窗口的OKbutton,Windows将WM_SETTINGCHANGE消息发送到所有顶级窗口,以通知正在运行的应用程序有关更改的系统参数。

如果这个事件消息是根本处理的并且如何处理,则由应用程序决定。 作为Windows桌面运行的Windows资源pipe理器从registry中读取环境variables,并相应地更新其环境variables列表。 像Total Commander这样的其他应用程序也会处理这个消息并更新它们的环境variables列表。 但是, cmd.exe并没有那样做,因为这将是真正的问题。

是否有可能通过命令提示符窗口或batch file中的WM_SETTINGCHANGE通知修改系统用户variables?

可以使用reg add命令修改环境variables的registry值。 但是这不会导致发送WM_SETTINGCHANGE消息到所有的顶级窗口。 使用reg addregedit完成的这些更改需要重新启动Windows(或至less注销并login当前用户)才能被考虑在内。

但是还有一个命令setx ,它被devise用来修改一个系统或者用户variables,并且在根据指定的参数更新registry之后,还把WM_SETTINGCHANGE消息发送到所有的顶级窗口。 运行setx /? 在命令提示符窗口中查看详细信息。 但请注意, setx不会修改运行命令进程的本地环境variables。 这必须通过使用除setx以外的命令setsetx

最有可能的是,你搞砸了PATHvariables。 也许你正在覆盖脚本中的其他地方。 由于sort是一个外部命令,与命令行中的所有其他命令相反, dirrdcmd -internal命令,所以需要使用PATHvariables来查找命令。 如果没有定义PATH则仅在当前工作目录中search外部命令。 还需要一个PATHEXTvariables来定义可执行文件的标准文件扩展名,如.com.exe 。 因此,当在命令提示符或batch file中出现sort时,系统会search当前工作目录和PATHvariables指定的所有目录,以查找具有基本名称sort的文件和PATHEXT指定的扩展名之一。 命令sort实际上称为sort.exe ,通常位于C:\Windows\System32