Just to expand a bit on Vlastimil's answer...
When the FOR command executes the "echo g" and pipes the output to findstr, FOR has to first start a new command processor which causes \blah\startfile.bat to be executed.
\blah\startfile.bat outputs a line containing sss ttt. That line is processed by FOR and is NOT passed to findstr.
According the the help for FOR:
Processing consists of ..., breaking it up into
individual lines of text and then parsing each line into zero or more tokens. The body of the for loop is then called with the variable value(s) set to the found token string(s). By default, /F
passes the first blank separated token from each line...
The default delimiters for FOR are: " ,;" (space comma and semi-colon).
The first line that FOR processes contains the string: sss ttt. That string contains a " " (space), which is a default delimiter for FOR, which parses the line and assigns the first token string: "sss" to "%f". So the "echo %f" outputs a line with only: "sss". That is the first line you see printed. The "ttt" is simply discarded because the "FOR ... echo %f" command did not specify to include anything more than the first token.
If the FOR command was written differently, you would have seen the full line "sss ttt" echoed.
Here are 3 ways the FOR command could have been written to do that.
The first way, using the "delims=" option, sets the delimiter for FOR to "empty", so FOR returns the entire line as 1 token. The tokens are still parsed, and all delimiters (" ,;") are removed, then all the tokens are combined again with a space between each token. This combined value is returned in the variable "%f"
C:\>for /f "delims=" %f in ('echo sss ttt') do echo %f
C:\>echo sss ttt
sss ttt
C:\>for /f "delims=" %f in ('echo mm;nn,oo, ;ss ,, tt') do echo %f
C:\>echo mm nn oo ss tt
mm nn oo ss tt
This next way, using the "tokens=*" option, tells FOR to put all of the tokens found into the value of the specified variable ("%f"). The tokens are still parsed, and all delimiters are removed, then all the tokens are combined again with a space between each token.
C:\>for /f "tokens=*" %f in ('echo sss ttt') do echo %f
C:\>echo sss ttt
sss ttt
C:\>for /f "tokens=*" %f in ('echo mm;nn,oo, ;ss ,, tt') do echo %f
C:\Users\1-kevin>echo mm nn oo ss tt
mm nn oo ss tt
This third way, using the "tokens=1,*" option, tells FOR to put the first (1) token found into the value of the specified variable ("%f"). And, the remaining tokens are parsed, and all delimiters are removed, then all those remaining tokens are combined again with a space between each token, and this combined value is returned in the variable named with the letter that follows the specified variable name (so in this case, variable "%g").
C:\>for /f "tokens=1,*" %f in ('echo sss ttt') do echo %f %g
C:\>echo sss ttt
sss ttt
C:\>for /f "tokens=1,*" %f in ('echo mm;nn,oo, ;ss ,, tt') do echo "%f" "%g"
C:\>echo "mm" "nn oo ss tt"
"mm" "nn oo ss tt"
Note that the following will not work because there are no "tokens=" defined for variables beyond the specified variable of "%f":
C:\>for /f %f in ('echo sss ttt') do echo %f %g
C:\>echo sss %g
sss %g
So, in your example, if you added the "delims=" option, you would see this:
C:\>for /f "delims=" %f in ('echo g ^| findstr "g"') do echo %f
C:\>echo sss ttt
sss ttt
C:\>echo g
g
C:\>