windows 即使标签存在,为什么会抛出“系统找不到指定的批次标签”?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/232651/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-09 05:36:19  来源:igfitidea点击:

Why "The system cannot find the batch label specified" is thrown even if label exists?

windowsbatch-filelabel

提问by Slimak

While running a batch file in Windows XP I have found randomly occurring error message:

在 Windows XP 中运行批处理文件时,我发现随机出现的错误消息:

The system cannot find the batch label specified name_of_label

系统找不到指定name_of_label的批次标签

Of course label existed. What causes this error?

标签当然存在。是什么导致了这个错误?

回答by VonC

Actually, you need 2 conditions for this to happen:

实际上,您需要两个条件才能发生这种情况:

  • the batch file must not use CRLF line endings
  • the label you jump to must span a block boundary (as opposed to and :end label wich is just a shortcut to the end of your script)
  • 批处理文件不得使用 CRLF 行尾
  • 您跳转到的标签必须跨越块边界(与 :end 标签相反,它只是脚本结尾的快捷方式)

See. The system cannot find the batch label specified(by and Batch-as-batch-can!

看。系统找不到指定的批次标签(by and Batch-as-batch-can!

David A. Graymentions in the commentsseeing (on Windows 10) what Marshal's answershowed in 2014 (presumably on Windows 7 or 8): a script/batch program (.bator .cmd) executed without CALLwould trigger an eol conversion.

David A. Gray在评论中提到(在 Windows 10 上)Marshal回答在 2014 年(大概在 Windows 7 或 8 上)显示的内容:执行的脚本/批处理程序(.bat.cmdCALL会触发 eol 转换。

I've written hundreds of batch scripts over the last 35 years, and the only time I've ever had an issue with labels not being found was when the file's line breaks got converted from Windows (CR/LF), which works, to Unix (LF), which doesn't.

在过去的 35 年里,我编写了数百个批处理脚本,唯一一次我遇到找不到标签的问题是当文件的换行符从 Windows (CR/LF) 转换为Unix (LF),它没有。



Feb. 2020, kinaradds in the comments:

2020 年 2 月,kinar在评论中补充

Just encountered this issue on a Win7 machine.
Turns out this error can also be generated when trying to CALL another .batfile if that file doesn't exist on the system.
In my case, I was trying to call the Visual Studio vcvarsall.batfile on a system without VS installed.

刚刚在Win7机器上遇到这个问题。
事实证明,.bat如果系统上不存在该文件,则在尝试调用另一个文件时也会生成此错误。
就我而言,我试图vcvarsall.bat在没有安装 VS 的系统上调用 Visual Studio文件。

See jeb's answerfor more: it was a case of an undefined label.

有关更多信息,请参阅jeb答案:这是一个未定义标签的情况。

回答by Marshal

I have got the same issue before. However, the root cause was not CRLF at all. It was because in the script I executed an external program such as Ant, but did not put a CALLbefore Ant. So, make sure you CALLevery external program used in your batch script.

我以前也遇到过同样的问题。但是,根本原因根本不是 CRLF。那是因为在脚本中我执行了一个外部程序,例如Ant,但没有CALL在Ant之前放一个。因此,请确保您CALL的批处理脚本中使用了每个外部程序。

回答by Masoud Kermani

Here is the issue and how to fix it. The issue is a bug or a feature in DOS batch cmd program. First the clear problem statement. If you have a DOS batch file with target labels like, ":dothis", and at the end of the label you do not have space then the batch file will not work if the line ending are UNIX line endings. This means you have to run unix2dos on the file before you can use it.

这是问题以及如何解决它。问题是 DOS 批处理 cmd 程序中的错误或功能。首先是明确的问题陈述。如果您有一个带有目标标签的 DOS 批处理文件,例如“:dothis”,并且在标签的末尾没有空格,那么如果行尾是 UNIX 行尾,则批处理文件将无法工作。这意味着您必须在文件上运行 unix2dos 才能使用它。

The root cause is the DOS command line processor, (shell program), takes the UNIX end-of-line character as part of the label. Since the go to part never uses this as the label, it is never found since such a label truly does not exist. The solution is to put an extra space at the end of each target label, or even better every line. Now UNIX end of lines do not come to play since the space acts as the separator and it all works.

根本原因是 DOS 命令行处理器(shell 程序)将 UNIX 行尾字符作为标签的一部分。由于 go to 部分从不使用 this 作为标签,因此永远不会找到它,因为这样的标签确实不存在。解决方案是在每个目标标签的末尾放置一个额外的空格,甚至更好地每行。现在 UNIX 行尾不再起作用,因为空格充当分隔符并且一切正常。

回答by Slimak

If batch file has unix line endings (line separators) this can sometimes happen.

如果批处理文件有 unix 行结尾(行分隔符),这有时会发生。

Just unix2dosit and problem should be solved.

只需使用unix2dos 即可解决问题。

回答by Slimak

You should also make sure that when calling other scripts you use CALL, instead of calling them in the caller's environment.

您还应该确保在调用其他脚本时使用 CALL,而不是在调用者的环境中调用它们。

回答by Greg

I encountered a similar issue just now with a .cmd file and Windows 8. The solution was to change all line endings to CR+LF DOS style. The issue was confusing because the batch file mostly worked and rearranging lines changed the effect.

我刚刚在 .cmd 文件和 Windows 8 中遇到了类似的问题。解决方案是将所有行结尾更改为 CR+LF DOS 样式。这个问题令人困惑,因为批处理文件主要工作,重新排列行改变了效果。

The .cmd file looked like:

.cmd 文件如下所示:

call:function_A "..\..\folderA\"
call:function_B "..\..\folderB\"
call:function_C "..\..\folderC\"
call:function_D "..\..\folderD\"
goto:eof

:function_A
rem do stuff
goto:eof

...etc...

Function C would cause error "The system cannot find the batch label specified". Strangely it could go away by rearranging the calls. Changing line endings from 0x0A to 0x0D0A seems to have fixed it.

函数 C 会导致错误“系统找不到指定的批次标签”。奇怪的是,它可以通过重新排列调用而消失。将行尾从 0x0A 更改为 0x0D0A 似乎已修复它。

Perhaps VonC meant "the batch file must use CRLF line endings".

也许 VonC 的意思是“批处理文件必须使用 CRLF 行尾”。

回答by Stefan Michev

i had this issue after copying a start command from word and paste it into the command window. There was a option with "-" on front, and thought the looks the same as the DOS "-" it wasn't :) After typing the "-" by myself the issue was solved and the batch worked ... a hard to find issue ....

从 word 复制启动命令并将其粘贴到命令窗口后,我遇到了这个问题。前面有一个带有“-”的选项,并认为它看起来与 DOS 中的“-”相同,但它不是 :) 在我自己输入“-”之后,问题就解决了,批处理工作......很难发现问题....

回答by jeb

There are multiple possible ways to get the error.

有多种可能的方法来获取错误。

  1. Described by VonC- Wrong line endings, LF instead of CR/LF

  2. Obscure long lines(if that happens accidential, your code is incredible worse)

  3. Direct start another batch after calling a function.
    Sample:

    @echo off
    call :func
    echo back from second
    exit /b
    :func second.bat echo NEVER COME BACK HERE
    This unexpectedly tries to gototo the label :funcin second.bat.
    But this can be (mis)-used to directly call labels in another batch file

  1. VonC 描述- 错误的行尾,LF 而不是 CR/LF

  2. 模糊的长行(如果这是偶然发生的,你的代码会更糟糕)

  3. 调用函数后直接启动另一个批处理。
    样本:

    @echo off
    call :func
    echo back from second
    exit /b
    :func second.bat echo NEVER COME BACK HERE
    这出乎意料地尝试到second.bat 中goto的标签:func
    但这可以(mis)- 用于直接调用另一个批处理文件中的标签

This is the described behaviour of the answer of Marshal

这是Marshal 的回答 所描述的行为

回答by Prasanna Mondkar

Little different use case ...

不同的用例...

I was calling a bat script during packerbuild of Windows Server 2012 Server, using the shellprovisioner (OpenSSH). Now, the script was working fine through cmd in the provisioned Virtual Machine (put breakpoint in packer build to stop and confirmed this) ... but, it was failing with these call labels not found issues.

我在Windows Server 2012 Server 的打包程序构建期间使用shell配置程序 (OpenSSH)调用了一个 bat 脚本。现在,脚本在预配的虚拟机中通过 cmd 运行良好(在打包程序构建中放置断点以停止并确认这一点)......但是,它因未找到这些调用标签的问题而失败。

The Line Endings were fine, CRLF (confirmed in Notepadd++). The script was working fine through command line as well. What more, sometimes, it just use to run fine and sometime fail, but once failed for some label, the failure was consistent.

行结尾很好,CRLF(在 Notepadd++ 中确认)。该脚本也通过命令行运行良好。更重要的是,有时,它只是用来运行良好,有时会失败,但是一旦某个标签失败,则失败是一致的。

Initially, I just started removing the subroutines altogether by expanding the call itself and putting subroutine code inline. I did this for all instances where there was only one call (no code duplication).

最初,我只是通过扩展调用本身并将子例程代码内联来完全删除子例程。对于只有一个调用(没有代码重复)的所有情况,我都这样做了。

But, yeah, i did stumble upon one sub which was called from 3,4 places. After trying everything, this is what worked for me

但是,是的,我确实偶然发现了一个从 3,4 个地方调用的潜艇。在尝试了一切之后,这对我有用

Adding 8-10 REM statements just above the subroutine. Yes, I am not kidding !!

在子例程上方添加 8-10 个 REM 语句。是的,我不是在开玩笑!!

PS : The script is very very old, but management needed me to make that work through packer (we have a Day-2 plan of this to replace it with Ansible/Chef).

PS:脚本非常非常旧,但管理层需要我通过打包程序来完成这项工作(我们有一个第 2 天的计划,用 Ansible/Chef 替换它)。