How to sort the (possibly empty) output of a for loop?

Discussion forum for all Windows batch related topics.

Moderator: DosItHelp

Message
Author
penpen
Expert
Posts: 1991
Joined: 23 Jun 2013 06:15
Location: Germany

Re: How to sort the (possibly empty) output of a for loop?

#16 Post by penpen » 11 Nov 2016 07:32

jeb wrote:It's obvious :D
The parser needs a none empty expression that is empty :!:
(...)
And as long as __CD__ exists, then zero characters from the front are in the most cases empty.

This should always work:

Code: Select all

(for %%a in (^,) do echo empty) | more


penpen

Edit: Removed "(maybe it needs additional "^^" on delayed expansion: untested)" because it is not neeeded; thanks @jeb.

Squashman
Expert
Posts: 4465
Joined: 23 Dec 2011 13:59

Re: How to sort the (possibly empty) output of a for loop?

#17 Post by Squashman » 11 Nov 2016 07:39

Here is an interesting observation.

When piping to MORE...

Code: Select all

@echo off
setlocal enabledelayedexpansion
(for %%a in (^,) do echo empty) | more
pause
endlocal
(for %%a in (%%__CD__:~0^,0%%) do echo %%a) | more
pause

Output

Code: Select all


Press any key to continue . . .

Press any key to continue . . .


But when piping to SORT....

Code: Select all

Press any key to continue . . .
Press any key to continue . . .

What is causing the empty lines when piping to MORE?

penpen
Expert
Posts: 1991
Joined: 23 Jun 2013 06:15
Location: Germany

Re: How to sort the (possibly empty) output of a for loop?

#18 Post by penpen » 11 Nov 2016 09:26

The program "more.exe" itself decides to behave this way:
Depends on the fact that the pipe is a file object, but contrary to "normal" files the end of data/stream cannot be predicted.
The reaction of consumers using a text stream (that may automatically removes special characters from stream, such as NUL) in the case of "data available" + "no data read" depends on the design decision of the author.

You should be able to see this behaviour on all "such" file objects; for example:

Code: Select all

<nul more
<nul sort


penpen

jeb
Expert
Posts: 1041
Joined: 30 Aug 2007 08:05
Location: Germany, Bochum

Re: How to sort the (possibly empty) output of a for loop?

#19 Post by jeb » 11 Nov 2016 10:33

penpen wrote:This should always work (maybe it needs additional "^^" on delayed expansion: untested) :
Code: Select all
(for %%a in (^,) do echo empty) | more


Much shorter and nicer than my version.

Delayed expansion hasn't any effect on the caret here, as in a pipe block delayed expansion isn't active (while parsing).

jfl
Posts: 226
Joined: 26 Oct 2012 06:40
Location: Saint Hilaire du Touvet, France
Contact:

Re: How to sort the (possibly empty) output of a for loop?

#20 Post by jfl » 12 Nov 2016 13:00

Aacini wrote:This does not crash:

Code: Select all

(cmd /C "for %i in () do @echo.%i") | sort

Sorry, I read your answer too fast.
No, when inserting cmd /c ahead of the killer command, this does not crash on my system either.
But I can't easily use this in my script, because the for loop has a complex 15-lines body. This would force using techniques like in macros for inserting line feeds in a string. And changing the number of ^ protecting various special characters everywhere. I don't have the courage to go through this now.

Squashman
Expert
Posts: 4465
Joined: 23 Dec 2011 13:59

Re: How to sort the (possibly empty) output of a for loop?

#21 Post by Squashman » 12 Nov 2016 15:30

I still would like to see a real world example of no output of a command inside a FOR /F in clause causing cmd.exe to crash like you stated in your first post.

jfl
Posts: 226
Joined: 26 Oct 2012 06:40
Location: Saint Hilaire du Touvet, France
Contact:

Re: How to sort the (possibly empty) output of a for loop?

#22 Post by jfl » 13 Nov 2016 12:08

Squashman wrote:I still would like to see a real world example of no output of a command inside a FOR /F in clause causing cmd.exe to crash like you stated in your first post.

I just spent two hours trying to recreate the script version that had this problem, and failed to reproduce it :-(
Unfortunately I never backed up that failing version. And in-between I did so many changes to attempt to work around this (and around the other issue about returning the exit code) that the code has changed beyond recognition.
Yet I'm positive here's how things happened: I have a parent script that filters the standard output of a child script, which lists selected values from the registry.
After making a change for sorting the values returned by the child script, I ran the parent script with a wrong argument, and entered the name of a registry key that did not exist. And the cmd shell crashed. Big surprise, as I've had all sorts of problems before, but never a cmd.exe crash! I repeated the test several times in a sub-shell (to keep the console open after the sub-shell crash), adding echos here and there to trace progress before the crash. I concluded that the inner script invoked in the for loop output an empty list of values from that non-existing key, then did return control successfully to the parent script. (I saw this by running something like: 'subcommand %1 ^| echo back alive'. Then the parent script crashed cmd before executing the for body.
Then I thought about trying directly at the cmd prompt the 0-times for loop I told you about in the beginning, and it too crashed cmd immediately. So I concluded perhaps too hastily that the 0-times for loop was the root cause, and never thought about preserving the exact source version that caused the crash. And now I can't seem to be able to reproduce it anymore with a for /f :-(

Post Reply