“…”是什么原因不被识别为内部或外部命令,可操作程序或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的PATHvariables:
-
用于所有帐户并存储在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和PATHEXTbatch 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 。
最有可能的是,你搞砸了PATHvariables。 也许你正在覆盖脚本中的其他地方。 由于sort是一个外部命令,与命令行中的所有其他命令相反, dir , rd是cmd -internal命令,所以需要使用PATHvariables来查找命令。 如果没有定义PATH则仅在当前工作目录中search外部命令。 还需要一个PATHEXTvariables来定义可执行文件的标准文件扩展名,如.com , .exe 。 因此,当在命令提示符或batch file中出现sort时,系统会search当前工作目录和PATHvariables指定的所有目录,以查找具有基本名称sort的文件和PATHEXT指定的扩展名之一。 命令sort实际上称为sort.exe ,通常位于C:\Windows\System32 。