I think I ran across a bug in a batch file because it was written with unix line endings. Is this a known problem with cmd.exe running batch files in windows?
-
1I have never had a problem, and I always use unix line endings. But that doesn't mean that there isn't some problem I have just been lucky enough to miss. – Zoredache Sep 18 '12 at 19:19
-
2Which bug did you run into? Commands failing to start? Or just that it looked as if there are not line endings when you open the file with notepad? – Hennes Sep 18 '12 at 19:21
5 Answers
This really isn't a "bug"... as it is by-design. Windows new-lines are defined as "\r\n" ... or a "Carriage Return" and "New Line" combination... whereas *nix flavors prefer omitting the carriage return. You should always use "\r\n" in anything in Windows where possible. Anything else may be interpreted incorrectly... and cause a great deal of unexpected results.
- 7,349
- 16
- 23
-
I came across an issue where call :label didn't jump to a label, but the same call later on the file did jump to the label. The file in question was using \n line endings. I switched to \r\n line endings for all batch files in my project and the problem was gone. I didn't re-test with \n endings to confirm it wasn't just a one-time fluke (the scripts takes nearly an hour to run). – Samuel Jun 19 '15 at 22:28
-
2Notepad can't handle Unix line endings, but WordPad can, PowerShell can, many other things can as well. – Michael Hampton Aug 08 '16 at 21:54
-
Cam you provide some more examples when .bat files do not work correctly with nix line endings? – Michal Kordas Apr 29 '19 at 18:19
-
@MichalKordas Without going through and testing every version of every Microsoft OS and *nix distribution, that's sort of a tall order to give. This really isn't the place to go into a detailed discussion on the subject. Best practices are such that Windows uses \r\n, *nix uses \n, and sometimes mac uses just a \r. Since Only Windows uses batch files, it's best to assume you should use \r\n. – TheCompWiz May 02 '19 at 15:40
-
@MichaelHampton: _Windows 10_ (in 2015) notepad does handle LF, finally. _And_ for UTF8 it no longer forces a nonstandard, useless and frequently harmful BOM :-) – dave_thompson_085 Sep 14 '21 at 07:12
For batch files there is no big difference between unix line endings and windows line endings.
Currently, there is only a glitch known for the behavior of GOTO and CALL, while searching for a label. The label parser fails to find a label, if the label is on a 512 byte boundary relative to the current file position. The difference is, because the carriage return is used for an internal line reset. See Call and goto may fail when the batch file has Unix line endings
Despite the label scanner, it's unexpected to find more problems, because the batch parser removes all carriage returns directly after the percent expansion phase.
Sample to show the problems:
@echo off
goto :main
:func
echo ************************************************
echo ************************************************
echo ************************************************
echo ************************************************
echo ************************************************
echo ***********************************************
echo ***********************************************
echo ***********************************************
echo ************************************************
echo never go back to :main
echo This is the end of :func
exit /b
:main
:main
echo This is main
goto :func
exit /b
The output is
This is the end of :func
- 335
- 3
- 10
-
This is not true. I know from experience. Unix line endings cases arbitrary failures when using gotos to jump to labels. – Simon Streicher Nov 25 '20 at 22:04
-
1@SimonStreicher You are right, there is a difference in the label parser. dbenham discovered that 2019 in [Call and goto may fail when the batch file has Unix line endings](https://www.dostips.com/forum/viewtopic.php?t=8988) – jeb Nov 26 '20 at 07:45
Kinda, but...
You will have to be a paranoid and
- always duplicate your label lines!
- never use colons outside of label definitions!
Eg.:
@echo off
goto main <- No use of colon
...
:main
:main <- Repeat label
echo At least one of the above labels are discoverable
REM main part done <- No use of colons in comments
How it works
When using Unix line endings, the label parser will skip over some labels because of an off-by-one error. This is due to the parser's use of 512-byte sized chunks and the assumption that line endings is denoted by two characters, \r\n
, rather than one, \n
. When a label is erroneously skipped over, the next erroneous skip can only occur at an offset of 512 bytes. If you duplicate a label on the next line, the duplicated label will be within the 512 limit, and can act as a fallback.
Furthermore, as demonstrated by @jeb, the parser also misinterprets the end of each 512-byte size chunk as a new line (as well as somehow ignoring white space characters between a colon and the next text on these pseudo lines). A comment such as :: main section
can trigger the parser into somehow reading the text : main
as the label :main
.
In summary, not only can the parser skip labels, it can also misinterpret comments and other pieces of text as labels.
Why not just stick with dos line endings?
It's not always safe to assume that your batch script will retain its line endings, especially when using Git or sharing content over GitHub. It's also convenient for cross platform projects not to care about line endings and assume Unix line endings as a common denominator.
- 141
- 3
-
1Nice idea to duplicate the labels. But it's not 100% safe, because it's possible that a `goto` or `call` ends at a complete wrong file position – jeb Sep 13 '21 at 17:51
-
Thanks @jeb. I can't seem to wrap my head around it, mind explaining some more? – Simon Streicher Sep 13 '21 at 20:11
-
This might be luck, but using the following example of wrong file position https://www.dostips.com/forum/viewtopic.php?t=8988#p58898 -> https://www.dostips.com/forum/download/file.php?id=421 , if I add a new line under `:test` as `:tst2` then I get the wrong file position as expected, but changing `:tst2` to `:test` the goto actually ends up at this new `:test` label as intended – Simon Streicher Sep 13 '21 at 20:44
-
I added a sample, that shows the problem and it doesn't help to duplicate the label – jeb Sep 14 '21 at 08:20
-
The answer is: you may get "lucky" and it will work with LF, but don't count on it. We had same problem as the original requestor. Our process would end up with bat files that were only LF, and (sorry could not find a pattern) sometimes a label would be 'not found', though clearly it was there. Would have to convert to CR-LF, or make random changes until it worked!
- 11
- 1