“X不被识别为内部或外部命令、可运行程序或批处理文件”是什么原因?

2024-02-18

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

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

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"

...它抛出标准错误:

排序不被识别为内部或外部命令

我在过去一个小时左右的时间里一直在尝试是否逃离管道,更改选项的顺序,查找两者的文档dir and sort等等,但我仍然无法弄清楚这里发生了什么。批处理文件的其余部分(只有几行)工作正常,这是其中唯一失败的行。


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

Windows 命令处理器搜索COMMAND执行哪个

  1. 不是内部命令cmd.exe and
  2. 仅指定文件名,不带文件扩展名,也不带路径

对于与模式匹配的文件command.* and本地环境变量中列出了文件扩展名PATHEXT

  1. 当前目录中的第一个and
  2. next 在本地环境变量的所有目录中PATH.

SORT and FIND and FINDSTR and ROBOCOPY and XCOPY还有更多命令不是内部命令cmd.exe。它们是随 Windows 安装的控制台应用程序,位于目录中%SystemRoot%\System32有文件名sort.exe, find.exe, findstr.exe, robocopy.exe, xcopy.exe, ...

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


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

有以下三种类型PATH变量:

  1. System PATH它用于所有帐户并存储在 Windows 注册表中的键下:

     HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\Environment
    
  2. User PATH仅用于当前帐户并存储在 Windows 注册表中的键下:

     HKEY_CURRENT_USER\Environment
    
  3. Local PATH这始终是一个copy当地的PATH启动当前进程的父进程。

Windows 连接system and user PATH to local PATH对于用作 Windows 桌面的 Windows 资源管理器实例,桌面屏幕上有快捷方式,Windows 开始菜单和 Windows 任务栏作为用户可见的界面Windows外壳 https://en.wikipedia.org/wiki/Windows_shell用户通常从中启动程序。

在启动新进程时,Windows 会将正在运行的进程的整个当前活动环境变量列表复制到新进程。 Windows内核库函数创建进程 https://learn.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-createprocessw该环境变量列表是否在函数参数上从当前进程的内存复制到新进程的内存lpEnvironment(指向环境的长指针)是空指针。中的一个CreateProcessWindows 上始终使用函数来从另一个可执行文件启动一个可执行文件。

父进程不能修改任何子进程的环境变量,子进程也不能修改其父进程的环境变量。

这意味着一旦像这样的过程cmd.exe启动是为了执行批处理文件,该进程有自己的一组环境变量,只有进程本身可以修改。任何其他进程都不能修改已运行进程的环境变量。


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

错误信息

'...' 不被识别为内部或外部命令,
可运行的程序或批处理文件。

总是意味着

  1. a 的文件名

    • 控制台应用程序
    • 图形用户界面应用程序
    • 脚本(批处理文件、PowerShell 脚本、Perl 脚本、VBScript、JScript...)


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

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


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

典型原因有:

1. 由于输入错误,指定了要执行的文件的文件名错误。

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

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

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

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

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

4. 执行文件的目录不在PATH at all.

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

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

的修改system PATH or user PATH用命令setx or via 控制面板-系统和安全-系统-高级系统设置-环境变量由用户或安装程序创建,但已运行的进程/应用程序(例如打开的命令提示符或 PowerShell 窗口)在之后未关闭/退出并打开/重新启动PATH修改。这是必要的,如章节中详细描述的F) below.

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

有目录%SystemRoot%\System32带有 64 位可执行文件和%SystemRoot%\SysWOW64在 64 位 Windows 上具有 32 位可执行文件,处理器也支持 x86 指令集。大多数可执行文件都存在于这两个目录中。但有一些可执行文件仅存在于System32和一些只在SysWOW64.

The system PATH默认包含作为第一个文件夹路径%SystemRoot%\System32。但会在两个 Windows 系统文件夹之一中搜索不带路径或带路径指定的可执行文件%SystemRoot%\System32取决于执行环境。在 64 位环境中执行的应用程序或脚本实际上是在访问%SystemRoot%\System32而在 32 位环境中执行的应用程序或脚本会被 Windows 重定向文件系统重定向器 https://learn.microsoft.com/en-us/windows/win32/winprog64/file-system-redirector到目录%SystemRoot%\SysWOW64.

在 32 位环境中运行的应用程序或脚本想要运行 64 位可执行文件%SystemRoot%\System32必须使用带有文件路径的可执行文件的完全限定文件名%SystemRoot%\Sysnative.

Note: %SystemRoot%\Sysnative既不是目录也不是任何类型的链接。它是仅针对 x86 应用程序而存在的非常特殊的东西。 amd64 应用程序不存在它。条件if exist %SystemRoot%\Sysnative批处理文件中的内容在两种环境中始终为 false,但是if exist %SystemRoot%\Sysnative\cmd.exe在 32 位执行环境中为 true,在 64 位环境以及 32 位 Windows 上为 false。该条件可用于批处理脚本中,以查明批处理文件是否由 32 位处理cmd.exe in %SystemRoot%\SysWOW64在 64 位 Windows 上,了解这一点可能很重要,具体取决于任务。

另请参阅 Microsoft 文档WOW64 实施细节 https://learn.microsoft.com/en-us/windows/win32/winprog64/wow64-implementation-details and 受 WOW64 影响的注册表项 https://learn.microsoft.com/en-us/windows/win32/winprog64/shared-registry-keys.

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

可以指定在PATH使用对另一个环境变量值的引用的文件夹路径,例如SystemRoot。重要的是,此环境变量也在同一组环境变量中定义,或者在 Windows 首先处理的一组环境变量中定义。

例如如果%JAVA_HOME%\bin被添加到system PATH环境变量,还必须定义一个system环境变量JAVA_HOME以及 Java 程序文件的基本文件夹路径。仅仅定义一个是不够的user环境变量JAVA_HOME或者定义环境变量JAVA_HOME后来在local批处理文件的环境。

%JAVA_HOME%\bin添加到user PATH如果环境变量被 Windows 扩展为完全限定的文件夹路径JAVA_HOME定义为system or as user环境变量,但未开启JAVA_HOME稍后定义localWindows 命令进程的环境。

这样的错误只要打开一个新的就很容易看出命令提示符 https://www.howtogeek.com/235101/10-ways-to-open-the-command-prompt-in-windows-10/修改后的窗口system or user PATH从 Windows 开始菜单并运行set path。输出PATH不应再包含任何%Variable%环境变量值参考。

8.LOCAL变量PATH之前在命令行或批处理文件中进行了修改。

Run set path在命令行上或将此命令添加到命令行上方的批处理文件中,但无法查看环境变量的当前值PATH and PATHEXT.

那个原因是负责外部命令的SORT执行包含上述某处的批处理文件时未找到set path=....

9. 局部变量PATH太长。

The local多变的PATH of cmd.exe太长。 Windows 命令处理器无法在以下文件夹路径中找到任何可执行文件/脚本local Path如果字符串值长于8191人物。

请参见我的第二个答案 https://stackoverflow.com/a/75050498/3074564此处有关长度限制的更多详细信息PATH.

感谢去阿尔伯特·莫西亚维克 https://stackoverflow.com/users/4926013/告知我程序或脚本无法识别的原因。


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

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

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

Any 外部命令其中可执行文件存储在%SystemRoot%\System32应在批处理文件中指定此路径和文件扩展名.exe。那么 Windows 命令解释器不需要使用以下命令来搜索文件local PATH and PATHEXT并且批处理文件始终有效(只要环境变量SystemRoot也没有在我从未见过的批处理文件中进行修改)。


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

当用户通过 Windows 开始菜单或 Windows 资源管理器窗口打开命令提示符窗口时,用户将启动cmd.exe带有隐式使用选项/K完成命令后保持控制台窗口打开,这有利于调试批处理文件。

当在 Windows 资源管理器中双击批处理文件时,用户将启动cmd.exe用于使用隐式使用选项处理批处理文件/C完成批处理后关闭控制台窗口,这不利于调试批处理文件,因为在这种情况下看不到错误消息。

在这两种情况下,Windows 都会创建应用程序启动时的环境变量的副本cmd.exe通常是 Windows 资源管理器。因此启动的命令进程有一个local PATH其值与父进程启动时的值相同cmd.exe.

Example:

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

  2. Run set PATH=%SystemRoot%\System32下一次set path.
    输出又是PATH and PATHEXT,但与PATH现在只包含一个目录。

  3. Run start "Process2"并在带有窗口标题的新控制台窗口中运行Process2命令set path.
    输出是PATH and PATHEXT具有与之前相同的值Process1.
    这表明在开始新流程时current运行进程的环境变量被复制,而不是 Windows 本身当前存储在 Windows 注册表中的环境变量。

  4. Run in Process2命令set PATH=接下来set path.
    输出仅PATHEXT因为local PATH不再存在Process2.
    这表明每个进程都可以修改其环境变量,包括完全删除。

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

  6. 运行命令start "Process3"并在打开的带有标题的窗口中Process3命令set path.
    输出是PATH有两个目录也定义为Process1 and PATHEXT.

  7. Run in Process3命令set PATH=%SystemRoot%\System32.

有 3 个命令进程正在运行,其值如下local PATH when %SystemRoot%扩展到C:\Windows:

Process1: PATH=C:\Windows\System32;C:\Windows
Process2: PATH根本不存在。
Process3: PATH=C:\Windows\System32

那么现在打开时会发生什么控制面板-系统-高级系统设置-环境变量并添加到列表中用户变量 the new环境变量PATH有价值C:\Temp,或者如果已经有一个user PATH环境变量,edit PATH并附加;C:\Temp到值?

好吧,只要对话框窗口有标题环境变量显示两个列表已打开,修改变量没有任何反应,直到按钮OK单击可将所有更改接管到 Windows 注册表中并关闭窗口。

我们回到三个运行命令进程,运行在Process1, Process2 and Process3命令set path。可以被看见:

Process1: PATH=C:\Windows\System32;C:\Windows
Process2: PATH根本不存在。
Process3: PATH=C:\Windows\System32

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

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

从 Windows 开始菜单中再打开一个命令提示符窗口并在第四个命令进程中运行该命令set path。可见local PATH第四个命令进程的已附加目录C:\Temp now.

然后关闭所有四个命令进程并删除添加的user PATH分别删除;C:\Temp from user PATH如果之前已附加此目录路径。

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

作为 Windows 桌面运行的 Windows 资源管理器实例的环境变量列表在关闭时如何修改环境变量带按钮的窗口OK?

这两个问题的答案由eryksun https://stackoverflow.com/users/205580/eryksun在他的评论中。

将修改写入后system and user单击按钮将变量存入注册表OK of 环境变量窗口,Windows 发送WM_SETTINGCHANGE https://learn.microsoft.com/en-us/windows/win32/winmsg/wm-settingchange向所有顶级窗口发送消息,以通知正在运行的应用程序有关更改的系统参数。

是否处理该事件消息以及如何处理由应用程序决定。作为 Windows 桌面运行的 Windows 资源管理器从注册表中读取环境变量并相应地更新其环境变量列表。其他应用程序(例如 Total Commander)也处理此消息并更新其环境变量列表。但cmd.exe幸运的是,不这样做,因为这确实会带来问题。

有没有可能修改system or user通过通知变量WM_SETTINGCHANGE从命令提示符窗口或批处理文件中?

可以使用以下命令修改环境变量的注册表值reg add命令。但这不会导致发送WM_SETTINGCHANGE向所有顶级窗口发送消息。此类更改完成reg add或与regedit需要重新启动 Windows(或至少注销并登录当前用户)。

但也有这样的命令setx这是专为修改system or user变量并且还发送WM_SETTINGCHANGE根据指定参数更新注册表后向所有顶级窗口发送消息。跑步setx /?在命令提示符窗口中了解详细信息。但请考虑到setx不修改local运行命令进程的环境变量。这必须使用命令来完成set除了使用setx.


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

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

System PATHEXT and user PATHEXT are NOT连接到local PATHEXT.

A user PATHEXT replaces the system PATHEXT对于在已定义的帐户环境下运行的所有进程user PATHEXT.

只定义了一个system PATHEXT默认环境变量。


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

如果在命令行或批处理文件中指定了脚本文件或可执行文件的文件名,而没有任何路径(即没有反斜杠),则 Windows 命令处理器默认在当前目录中搜索\(或正斜杠/感谢参数字符串中的自动更正)。

但在 Windows Vista 和更高版本的 Windows 客户端版本以及 Windows Server 2003 和更高版本的 Windows 服务器版本上,确实可以禁用在至少没有相对路径的情况下指定的当前目录中搜索脚本/可执行文件.\通过定义环境变量NoDefaultCurrentDirectoryInExePath具有写入的任何值eryksun https://stackoverflow.com/users/205580/eryksun在他下面的评论中,并由微软有关功能的文档进行了解释NeedCurrentDirectoryForExePathA https://learn.microsoft.com/en-us/windows/win32/api/processenv/nf-processenv-needcurrentdirectoryforexepatha.

See 从路径中删除当前工作目录 https://stackoverflow.com/questions/50064901/有关此环境变量的使用的更多详细信息。


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

The system and user PATH用户最好使用 Windows GUI 对话框窗口修改环境变量环境变量。该对话框窗口可以按如下方式打开:

  1. 单击 WindowsStart菜单按钮。
  2. 在键盘上输入环境变量.
  3. Windows 提供了两项:
    编辑系统环境变量
    编辑您帐户的环境变量
  4. 单击两个项目之一以打开环境变量 window.

也可以打开Windows控制面板。必须有下一步点击系统和安全 with Category选择显示选项View by。必须点击下一步System。必须点击左侧高级系统设置然后点击按钮环境变量...

The System window can be opened also by pressing the key combination Windows logo key + Pause if the keyboard has the key Pause at all or at least in combination with the key Fn. See also the Microsoft documentation page Keyboard shortcuts in Windows https://support.microsoft.com/en-us/windows/keyboard-shortcuts-in-windows-dcc61a57-8ff0-cffe-9796-cb9706c75eec.

进一步的用户操作是不言自明的,可以编辑user Path在现有的上列表中或system Path在下面的列表中。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

“X不被识别为内部或外部命令、可运行程序或批处理文件”是什么原因? 的相关文章

  • Windows 中“nice”的等效词

    Windows 中是否有相当于 Unix 命令的命令 nice 我正在专门寻找可以在命令行中使用的东西 并且not任务管理器中的 设置优先级 菜单 我在谷歌上寻找这个的尝试被那些想不出更好形容词的人挫败了 如果您想在启动进程时设置优先级 您
  • 如何用C语言测量时间?

    我想知道某个代码块执行了多长时间 大约 像这样的事情 startStopwatch do some calculations stopStopwatch printf lf timeMesuredInSeconds How 您可以使用clo
  • 连接到 VPN 时 HttpClient.GetAsync 超时

    当系统不使用 VPN 时 C 4 5 2 框架 HttpClient GetAsync 方法在 Windows 10 上运行良好 连接 VPN 后 对同一地址的 HttpClient GetAsync 调用只会阻塞 直到超时 Edge 和
  • 如何将 man 和 zip 添加到 Windows 上的“git bash”安装中

    我在用git bash https git for windows github io 在 Windows 上 即git对于 Windows 通过集成bash 显然它使用的是MINGW MSYS支撑 来自 VonC 的更新 现在使用 msy
  • 批处理 - 默认浏览器?

    有没有办法使用批处理文件查找我的计算机上的默认浏览器 只需使用 启动 www google com See here http social msdn microsoft com Forums is iewebdevelopment thr
  • Windows 内存映射文件

    我正在尝试研究 Windows 内核在内存映射文件 虚拟内存方面的行为 具体来说 我感兴趣的是确定内存映射文件的内容 由 Windows 刷新到磁盘的频率以及 Windows 使用什么标准来决定是时候这样做 我在网上做了一些研究 除了 MS
  • 模拟后 CreateMutex 失败

    这是我尝试模拟用户然后创建互斥体的代码 未创建互斥体 我收到 ERROR ACCESS DENIED 错误 void Impersonate DWORD logonType LOGON32 LOGON INTERACTIVE DWORD l
  • 使用 .NET 在 Windows 中创建弹出式“烤面包机”通知

    我正在使用 NET 并创建一个桌面应用程序 服务 当触发某些事件时 它将在桌面的一角显示通知 我不想使用常规的消息框 b c 那样会造成太大的干扰 我希望通知滑入视图 然后在几秒钟后淡出 我正在考虑一种类似于 Outlook 收到新邮件时发
  • 从 Windows 中的 C++ 应用程序进行 Thrift 调用

    正如标题所示 我有一个用 C 编写的 Windows 应用程序 我需要从中调用远程 Thrift 服务 说实话 我对这个主题有点迷失 http wiki apache org thrift ThriftInstallationWin32 h
  • 任务中的 ConEmu 命令

    我试图在 ConEmu 中获取一个任务来打开多个控制台 并在每个控制台打开时运行一个类似批处理的脚本 例如 打开 Git Bash 将控制台命名为 X 将当前目录设置为 Y 打开另一个 Git Bash 并运行一组命令 例如 cd A B
  • 如何访问窗口?

    我正在尝试使用其句柄访问特定窗口 即System IntPtr value Getting the process of Visual Studio program var process Process GetProcessesByNam
  • 使用 System.Security.Cryptography 将 Win32 Crypto API 调用转换为 C#

    我接到一项任务 要删除我们产品的一个 dll 并将其替换为纯 C 的 dll 旧的 DLL 是 NET 2 0 托管 C C CLI 它包装了对 Win32 本机加密 API 的调用 新的 DLL 应公开具有相同名称和方法的新对象 但应使用
  • Powershell 设置盖子关闭操作

    我想自动设置 Windows 7 在我的工作笔记本电脑上合上盖子时所执行的操作 因为每次登录时都会通过 GPO 重置该操作 我知道我可以在批处理脚本中使用 powercfg 命令来实现此目的 powercfg setacvalueindex
  • 午夜后时间设置不正确

    我使用以下命令以更易读的格式获取当前日期 时间 set day date 4 2 set mth date 7 2 set yr date 10 4 set hur time 0 2 set min time 3 2 set bdate d
  • 多重处理:如何从子进程重定向标准输出?

    注意 我见过multiprocessing Process 的日志输出 https stackoverflow com questions 1501651 log output of multiprocessing process 不幸的是
  • 如何驯服 Windows 标头(有用的定义)?

    在其中一个答案中this https stackoverflow com questions 1394132 macro and member function conflict问题jalf https stackoverflow com
  • Windows 上的 wchar_t 和 char16_t 是一样的吗?

    我有一个实例std u16string 我可以通过它吗c str 到一个 Win32 API 它期望LPCWSTR 没有任何类型的转换 例如 我可以安全地这样做吗 auto u16s std u16string u Hello SetWin
  • 无法在 Windows 7 机器中使用 OpenCV 2.4.3、Python 2.7 打开“.mp4”视频文件

    我目前正在进行一个涉及读取 mp4 视频文件的项目 我遇到的问题是它在Windows 7机器上使用Python 2 7 32位 OpenCV 2 4 3 cv2 pyd 代码片段如下 try video cv2 VideoCapture v
  • c 编程检查是否按下按键而不停止程序

    如您所知 在 Windows 中使用 getch 时 应用程序会等待您按下某个键 我如何在不冻结程序的情况下读取密钥 例如 void main char c while 1 printf hello n if c getch 谢谢 您可以使
  • 如何列出静态链接的 python 版本中可用的所有 openssl 密码?

    在python 2 7 8到2 7 9升级中 ssl模块从使用更改为 DEFAULT CIPHERS DEFAULT aNULL eNULL LOW EXPORT SSLv2 to DEFAULT CIPHERS ECDH AESGCM D

随机推荐