Excellent and interesting question (+1)
The space is introduced by the pipe mechanism of the CMD parser, not by SORT.
When you execute a command using FOR /F, the command is executed in its own CMD shell. Also, each side of a pipe is executed in its own CMD shell. See Why does delayed expansion fail when inside a piped block of code? for more info.
So your command actually instantiates 3 CMD shells, one for the FOR /F command, which in turn creates 2 for each side of the pipe.
You can see how the commands get parsed and fed into the CMD shell using the %CMDCMDLINE% dynamic variable. Because we are executing the command from the command line, we need to escape at least one character in the variable name twice so that it doesn't get expanded until it reaches the inner most CMD shell.
Here is the command with the results (the leading >
is my command prompt):
>for /f "delims=" %a in ('(echo %^^^cmdcmdline%^&for /l %z in (1,1,10^) do @echo %z^)^|sort') do @echo %a0
1 0
10 0
2 0
3 0
4 0
5 0
6 0
7 0
8 0
9 0
C:Windowssystem32cmd.exe /S /D /c" ( echo %cmdcmdline% & FOR /L %z in (1 1 10) do @ echo %z )" 0
The last line of output is the command line used for the left side of the pipe. You can see how the parser added spaces in a number of places.
You can circumvent the problem by using a simple batch script to echo the value instead of the ECHO command.
echoArgs.bat
@echo(%*
Now when you run this command you get the desired result
>for /f "delims=" %a in ('(for /l %z in (1,1,10^) do @echoArgs %z^)^|sort') do @echo %a0
10
100
20
30
40
50
60
70
80
90
Another method to circumvent the problem is to create a variable with your ECHO command and escape the expansion of the variable appropriately.
>set cmd=@(echo %z)
>for /f "delims=" %a in ('(for /l %z in (1,1,10^) do %^^^cmd%^)^|sort') do @echo %a0
10
100
20
30
40
50
60
70
80
90
EDIT
The >_tempfile echo and here's a space|more
example is also interesting. There is an extra space at the end of the output file. But Chad Nouis is correct that nothing is being sorted because of the redirection of the left side. Any command could be used on the right side and the result would be the same.
The source of the problem is still the parser, but the way the parser restructures the commmand is interesting.
>>_tempfile echo %^cmdcmdline%|rem
>type _tempfile
C:Windowssystem32cmd.exe /S /D /c" echo %cmdcmdline% 1>_tempfile"
Notice how the redirection is moved from the beginning to the end of the command, and the file handle of 1
is explicitly added. You can certainly see where the extra space comes from.