“…”是什么原因不被识别为内部或外部命令,可操作程序或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道,改变选项的顺序,查找dir
和dir
的文件等,但我仍然无法弄清楚是什么去这里 batch file的其余部分,只有几行,工作正常,这是唯一的行失败。
谁能帮忙? 在此先感谢,我真的很感激。
A)Windows命令解释器如何search命令?
Windows命令解释器search命令来执行哪个
- 不是
cmd.exe
的内部命令 - 只是用没有文件扩展名和没有path的文件名指定的
匹配模式command.*
的文件, 并在本地环境variablesPATHEXT
列出文件扩展名
- 首先在当前目录中
- 接下来在本地环境variables
PATH
所有目录中。
SORT和FIND和FINDSTR和ROBOCOPY和XCOPY以及更多的命令不是cmd.exe
内部命令。 它们是安装在Windows中的控制台应用程序,位于具有文件名sort.exe
, find.exe
, findstr.exe
, robocopy.exe
, xcopy.exe
目录%SystemRoot%\System32
中…
Windows上默认可用的这种控制台应用程序称为外部命令,以便将其与未安装Windows操作系统的控制台应用程序区分开来。
B)如何定义环境variablesPATH?
有三种types的PATH
variables:
-
用于所有帐户并存储在Windowsregistry项下的系统
PATH
:HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\Environment
-
用户
PATH
只用于当前帐户并存储在Windowsregistry项下:HKEY_CURRENT_USER\Environment
-
本地
PATH
,它始终是启动当前进程的父进程的本地PATH
的副本 。
Windows将用于Windows桌面的Windows资源pipe理器实例的系统和用户 PATH
连接到本地 PATH
,桌面屏幕上的快捷方式和Windows开始菜单作为用户的可见界面。
在启动一个新进程时,运行进程的整个当前活动的环境variables表被复制到Windows的新进程中。
父进程不能修改任何subprocess的环境variables,subprocess也不能修改其父进程的环境variables。
这意味着一旦像cmd.exe
这样的进程开始执行batch file,进程就拥有自己的一组环境variables,只有进程本身才能修改。 没有其他进程可以修改已经运行的进程的环境variables。
C)错误信息是什么意思?
错误消息
“…”不被识别为内部或外部命令,
可操作程序或batch file。
总是意味着
-
a的文件名
- 控制台程序
- GUI应用程序
- 脚本(batch file,PowerShell脚本,Perl脚本,VBScript,JScript,…)
被指定执行,很可能没有文件扩展名,也没有(完整)path到可执行文件/脚本文件和
-
Windows无法find与当前活动环境variables
PATH
中当前活动环境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中,该命令行无法看到环境variablesPATH
和PATHEXT
的当前值。
最后的原因是负责外部命令SORT不被执行的batch file,其中包含上面set path=...
以上的地方。
E)如何避免这个错误信息?
最好是编写一个独立的PATH
和PATHEXT
batch 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命令解释器不需要使用本地 PATH
和PATHEXT
来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
的值相同。
例:
-
打开命令提示符窗口,运行
title Process1
并运行set path
。
输出是当前在控制台窗口中为当前用户帐户定义的PATH
和PATHEXT
,现在具有窗口标题Process1 。 -
运行
set PATH=%SystemRoot%\System32
,然后再次set path
。
输出再次是PATH
和PATHEXT
,但PATH
只包含一个目录。 -
运行
start "Process2"
并在窗口标题Process2的新控制台窗口中运行命令set path
。
输出是PATH
和PATHEXT
,与Process1中的值相同。
这表明在启动一个新进程时,运行进程的当前环境variables被复制,而不是Windows本身当前存储在Windowsregistry中的内容。 -
在Process2中运行命令
set PATH=
和下一个set path
。
输出只是PATHEXT
因为Process2中不存在本地PATH
。
这表明每个进程都可以修改其环境variables,包括完全删除。 -
切换到Process1窗口,运行命令
set PATH=%PATH%;%SystemRoot%
和下一个set path
。
输出是PATH
与两个目录和PATHEXT
。 -
运行命令
start "Process3"
并在打开的窗口中用标题Process3命令set path
。
输出是PATH
,同时也为Process1和PATHEXT
定义了两个目录。 -
在Process3中运行命令
set PATH=%SystemRoot%\System32
。
当%SystemRoot%
扩展到C:\Windows
时,有3个命令进程使用以下值作为本地 PATH
运行:
Process1 : PATH=C:\Windows\System32;C:\Windows
Process2 : PATH
根本不存在。
Process3 : PATH=C:\Windows\System32
那么现在打开控制面板 – 系统 – 高级系统设置 – 环境variables ,并向用户variables列表添加值为C:\Temp
的新环境variablesPATH
,或者在已经有用户 PATH
环境variables的情况下, 编辑 PATH
并追加;C:\Temp
的值?
那么,只要打开标题Environment Variables显示两个列表的对话窗口被打开,修改variables就不会发生任何事情,直到单击OKbutton接pipeWindowsregistry中的所有更改并closures窗口。
让我们回到3个运行命令进程,并在Process1 , Process2和Process3中运行命令set path
。 可以被看见:
Process1 : PATH=C:\Windows\System32;C:\Windows
Process2 : PATH
根本不存在。
Process3 : PATH=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 add
或regedit
完成的这些更改需要重新启动Windows(或至less注销并login当前用户)才能被考虑在内。
但是还有一个命令setx
,它被devise用来修改一个系统或者用户variables,并且在根据指定的参数更新registry之后,还把WM_SETTINGCHANGE
消息发送到所有的顶级窗口。 运行setx /?
在命令提示符窗口中查看详细信息。 但请注意, setx
不会修改运行命令进程的本地环境variables。 这必须通过使用除setx
以外的命令set
来setx
。
最有可能的是,你搞砸了PATH
variables。 也许你正在覆盖脚本中的其他地方。 由于sort
是一个外部命令,与命令行中的所有其他命令相反, dir
, rd
是cmd
-internal命令,所以需要使用PATH
variables来查找命令。 如果没有定义PATH
则仅在当前工作目录中search外部命令。 还需要一个PATHEXT
variables来定义可执行文件的标准文件扩展名,如.com
, .exe
。 因此,当在命令提示符或batch file中出现sort
时,系统会search当前工作目录和PATH
variables指定的所有目录,以查找具有基本名称sort
的文件和PATHEXT
指定的扩展名之一。 命令sort
实际上称为sort.exe
,通常位于C:\Windows\System32
。