Has*_*him 3 windows cmd batch-file
我有一个在命令行中完美运行的单行代码段,但在我作为批处理脚本的一部分运行时失败并引发错误.
以下命令按预期运行,删除文件夹中的所有空子文件夹.
for /f "delims=" %d in ('dir /s /b /ad ^| sort /r') do rd "%d"
Run Code Online (Sandbox Code Playgroud)
但是,当放入批处理文件时...
FOR /f "delims=" %%d in ('dir /s /b /ad ^| sort /r') do rd "%%d"
Run Code Online (Sandbox Code Playgroud)
...它抛出了标准错误:
排序不被识别为内部或外部命令
我一直在尝试了一个小时左右,有和没有逃脱管,改变的选项的顺序,查找两者的文件dir
和sort
等等,但我还是没能弄清楚这是怎么回事这里.批处理文件的其余部分(只有几行)工作正常,这是其中唯一失败的行.
有人可以帮忙吗?
Mof*_*ofi 16
Windows命令解释程序搜索要执行的命令
cmd.exe
,并对于匹配模式的文件,command.*
并在本地环境变量中列出文件扩展名PATHEXT
PATH
.SORT和FIND以及FINDSTR和ROBOCOPY以及XCOPY等许多命令都不是内部命令cmd.exe
.他们与位于目录中安装了Windows控制台应用程序%SystemRoot%\System32
具有文件名sort.exe
,find.exe
,findstr.exe
,robocopy.exe
,xcopy.exe
,...
Windows上默认提供的此类控制台应用程序称为外部命令,可以更好地区分它们与未安装Windows操作系统的控制台应用程序.
有三种类型的PATH
变量:
系统 PATH
用于所有帐户并存储在Windows注册表下的密钥:
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\Environment
Run Code Online (Sandbox Code Playgroud)用户 PATH
仅用于当前帐户并存储在Windows下的Windows注册表中:
HKEY_CURRENT_USER\Environment
Run Code Online (Sandbox Code Playgroud)本地 PATH
,它始终是启动当前进程的父进程的本地副本PATH
.
Windows 将用作Windows桌面的Windows资源管理器实例的系统和用户 连接PATH
到本地 PATH
,桌面屏幕上的快捷方式和Windows开始菜单作为用户的可见界面.
在启动新进程时,Windows将为新进程复制正在运行的进程的整个当前活动环境变量表.
父进程不能修改任何子进程的环境变量,子进程也不能修改其父进程的环境变量.
这意味着一旦cmd.exe
开始执行批处理文件的过程,该进程就有自己的一组环境变量,只有进程本身才能修改.没有其他进程可以修改已在运行的进程的环境变量.
错误消息
'...'不被识别为内部或外部命令,
可操作程序或批处理文件.
总是意味着
文件名
指定执行很可能没有文件扩展名,没有(完整)路径到可执行文件/脚本文件和
Windows无法找到与模式匹配的FileName.*
文件PATHEXT
,其中包含当前目录中当前活动环境变量中列出的文件扩展名或当前活动环境变量中的任何其他目录PATH
.
典型的原因是:
1.由于输入错误,要执行的文件的文件名指定错误.
逐个字符检查命令/可执行文件的名称.
2.当前目录与包含要执行的文件的目录不同.
echo Current directory is: %CD%
在命令行上运行或将此行添加到命令行上方的批处理文件中,该文件无法查看当前目录是什么.
3.根本没有安装要运行的可执行文件或脚本.
验证是否存在要运行的可执行文件.某些安装包仅在以前安装了Java,NPM,PHP等其他软件包时才有效.
4.要执行的文件的目录根本不存在 PATH
.
在Windows 控制面板的" 系统设置"窗口中打开,单击左侧的" 高级系统设置 ",单击" 环境变量 "按钮,然后查看两个列表Path
及其值.默认情况下Path
,仅存在于系统变量列表中.
5.修改系统或用户后,未重新启动正在运行的进程/应用程序 PATH
.
使用命令或通过控制面板进行系统 PATH
或用户的 修改- 系统 - 高级系统设置由用户或安装程序进行,但是已打开的进程/应用程序(如打开的命令提示符或PowerShell窗口)未关闭/退出并打开/ 修改后重新启动.这是必要的,如下面F)部分所述.PATH
setx
PATH
6. 在命令行或批处理文件之前修改了LOCAL变量%SystemRoot%\System32
.
运行%SystemRoot%\System32
命令行或添加此命令到无法看到的环境变量的当前值的命令行上面的批处理文件%SystemRoot%\SysWOW64
和System32
.
最后一个原因是在执行包含上述某处的批处理文件时找不到外部命令SORTSysWOW64
.
Best编写了一个批处理文件,用于独立于PATH
和%SystemRoot%\System32
目录的顺序,%SystemRoot%\System32
这意味着在这里使用命令行:
FOR /f "delims=" %%d in ('dir /s /b /ad ^| %SystemRoot%\System32\sort.exe /r') do rd "%%d"
Run Code Online (Sandbox Code Playgroud)
存储可执行文件的任何外部命令%SystemRoot%\System32
都应在具有此路径和文件扩展名的批处理文件中指定%SystemRoot%\SysWOW64
.然后,Windows命令解释器不需要使用本地 搜索文件%SystemRoot%\System32
,%SystemRoot%\Sysnative
并且批处理文件始终有效(只要环境变量%SystemRoot%\Sysnative
也未在批处理文件中修改,我从未见过).
当用户通过Windows开始菜单或在Windows资源管理器窗口中打开命令提示符窗口时,用户if exist %SystemRoot%\Sysnative
以隐式使用选项启动,if exist %SystemRoot%\Sysnative\cmd.exe
以在完成适合调试批处理文件的命令后保持控制台窗口打开.
在Windows资源管理器中双击cmd.exe
批处理文件时,用户启动处理批处理文件,并使用隐式使用选项%SystemRoot%\SysWOW64
在完成批处理后关闭控制台窗口,这对于调试批处理文件不利,因为在这种情况下无法看到错误消息.
在这两种情况下,Windows都会创建应用程序环境变量的副本,PATH
通常是Windows资源管理器.因此,启动的命令进程具有本地, PATH
其值与父进程在启动时的值相同SystemRoot
.
例:
打开命令提示符窗口,运行%JAVA_HOME%\bin
并运行PATH
.
输出是JAVA_HOME
与JAVA_HOME
如目前用于在具有现在窗口标题控制台窗口当前用户帐户中定义处理1.
JAVA_HOME
再次运行和下一次%JAVA_HOME%\bin
.
输出仍PATH
和JAVA_HOME
,但JAVA_HOME
现在只包含一个目录.
PATH
在新的控制台窗口中运行并运行,窗口标题为Process2命令set path
.
输出与Process1中的值相同PATH
且%Variable%
具有相同的值.
这表明在启动新进程时,将复制正在运行的进程的当前环境变量,而不是Windows本身当前存储在Windows注册表中的那些变量.
在Process2中运行命令PATH
,然后运行set path
.
输出仅仅PATH
是因为Process2不再存在本地 .
这表明每个进程都可以修改其环境变量,包括完全删除.PATHEXT
切换到处理1窗口中运行命令set path=...
和未来PATH
.
输出PATHEXT
有两个目录和PATH
.
运行命令%SystemRoot%\System32
并在打开的窗口中使用标题Process3命令.exe
.
输出PATH
有两个目录,也为Process1和PATHEXT
.
在Process3中运行命令SystemRoot
.
当扩展为:时,有3个命令进程在运行时具有以下本地 值:cmd.exe
/K
cmd.exe
Process1:/C
Process2:cmd.exe
根本不存在.
过程3:PATH
那么现在在打开控制面板 - 系统 - 高级系统设置 - 环境变量以及向用户变量列表中添加带有值的新环境变量cmd.exe
时title Process1
,或者如果已经有用户 set path
环境变量,编辑 PATH
并附PATHEXT
加到值会发生什么?
好吧,只要打开带有显示两个列表的标题环境变量的对话框窗口,修改变量就没有任何反应,直到单击按钮确定以将所有更改接管到Windows注册表并关闭窗口.
让我们回到3个运行命令进程,并在Process1,Process2和Process3中运行命令set PATH=%SystemRoot%\System32
.可以被看见:
Process1:set path
Process2:PATH
根本不存在.
过程3:PATHEXT
已经运行的进程没有任何改变.
没有进程可以修改正在运行的进程的环境变量.
从Windows开始菜单打开另一个命令提示符窗口并在第四个命令中运行命令处理PATH
.可以看出,第四个命令进程的本地 现在start "Process2"
已经附加了该目录set path
.
然后关闭所有4个命令进程并删除添加的用户 ,如果之前已添加此目录路径,则PATH
分别PATHEXT
从用户 删除set PATH=
.
如果没有进程可以修改已经运行的进程的环境变量,那怎么可能呢?
如果在关闭环境变量窗口时使用按钮确定,Windows资源管理器实例的环境变量列表是如何运行的?
关于这两个问题的答案是由eryksun在他的评论中给出的.
在单击" 环境变量"窗口的" 确定 " 窗口中将系统 和用户变量的修改写入注册表后,Windows会将WM_SETTINGCHANGE消息发送到所有顶级窗口,以通知正在运行的应用程序有关已更改的系统参数的信息.
如果完全处理此事件消息以及如何处理,则由应用程序决定.运行为Windows桌面的Windows资源管理器从注册表中读取环境变量并相应地更新其环境变量列表.Total Commander等其他应用程序也处理此消息并更新其环境变量列表.但set path
幸运的是,这不会那样做,因为这确实存在问题.
是否有可能通过命令提示符窗口或批处理文件中的通知来修改系统或用户变量PATHEXT
?
可以使用PATH
命令修改环境变量的注册表值.但这不会导致set PATH=%PATH%;%SystemRoot%
向所有顶级窗口发送消息.使用set path
或完成此类更改PATH
需要重新启动Windows(或至少注销并登录当前用户)才能完全考虑.
但是还有一个命令PATHEXT
用于修改系统或用户变量,并且start "Process3"
在根据指定的参数更新注册表之后还将消息发送到所有顶级窗口.set path
在命令提示符窗口中运行以获取详细信 但请注意PATH
不要修改运行命令进程的本地环境变量.必须PATHEXT
使用除此之外使用的命令来完成此操作set PATH=%SystemRoot%\System32
.
与环境变量相比,PATH
具有文件扩展名列表的环境变量由Windows处理%SystemRoot%
.
系统 C:\Windows
和用户 PATH=C:\Windows\System32;C:\Windows
都不要串接到本地 PATH
.
甲用户 PATH=C:\Windows\System32
替换的系统 PATH
下具有帐户的环境中运行的所有过程的用户 C:\Temp
定义的.
默认情况下,仅定义了系统 PATH
环境变量.
Windows命令处理器默认搜索当前目录中是否在命令行或批处理文件中指定了脚本文件或可执行文件的文件名而没有任何路径,这意味着参数字符串中没有反斜杠PATH
(或者;C:\Temp
由于自动更正而产生正斜杠) .
但是在Windows Vista和更高版本的Windows客户端版本以及Windows Server 2003和更高版本的Windows服务器版本上,set path
通过PATH=C:\Windows\System32;C:\Windows
使用任何写入的值定义环境变量,确实可以禁用在指定的当前目录中搜索脚本/可执行文件而不至少具有相对路径由eryksun在下面的评论中解释并由Microsoft在MSDN文章中解释函数NeedCurrentDirectoryForExePath.
有关此环境变量使用的更多详细信息,请参阅从路径中删除当前工作目录.
最有可能的是,你搞砸了这个PATH
变量.也许你会在脚本中的其他地方覆盖它.由于sort
是一个外部命令,不是所有的人在你的命令行一样for
,dir
,rd
,这是cmd
-internal命令时,PATH
需要变量来查找命令.如果PATH
未定义,则仅在当前工作目录中搜索外部命令.还有一种PATHEXT
是需要定义标准的文件扩展名可执行文件,如变量.com
,.exe
.因此,当sort
出现在命令提示符或批处理文件中时,系统将搜索当前工作目录和PATH
变量指定的所有目录,以查找具有基本名称sort
和指定的扩展名之一的文件PATHEXT
.该命令sort
实际上是被调用的sort.exe
,通常位于C:\Windows\System32
.