Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why don't some "for" commands work when the output is piped?

As an example of the problem I'm seeing, the command

for /D %%i in (*) do @if not exist m:\home\%%i echo %%i

gives me a list of directories in the current directory that don't exist in the other directory.

However, if I want to pipe the output to another command, for example:

(for /D %%i in (*) do @if not exist m:\home\%%i echo %%i) | findstr /n .

I get this error message:

echo was unexpected at this time.

Note that I can't just leave the brackets out, because that would result in the pipe operator being processed once per iteration of the loop; I need the output of the loop piped to a single instance of an application. For example, if I leave the brackets out in this example, the line number from findstr will always be shown as 1 rather than counting the number of directories.

Does anybody know how to make this work, preferably in the general case rather than just this specific example?

Windows 7 SP1 x64.

like image 437
Harry Johnston Avatar asked Sep 29 '22 13:09

Harry Johnston


2 Answers

It's a problem of the parser with special IF syntax forms like:

IF exist
IF defined
IF errorlevel
IF x EQU y

But this one works without problems

IF x == y

It can be solved with defining a variable containing a single IF.

set "_IF_=IF"
( %%_IF_%% defined path echo It's defined ) | more
( %%_IF_%% errorlevel 0 echo Errorlevel is 0 or above ) | more

This works, as the %%_IF_%% will be expanded not before the child process parses the block.

like image 115
jeb Avatar answered Oct 03 '22 06:10

jeb


As per Eryksun's comments, this is definitely a bug. It can be worked around by explicitly creating a child process, rather than letting the batch processor do it for you:

cmd /s /c "for /D %%i in (*) do @if not exist m:\home\%%i echo %%i" | findstr /n .

Another option is to manually inject the missing space, by defining %space% to be a single space and saying:

(for /D %%i in (*) do @if not exist ^%%space^%% m:\home\%%i echo %%i) | findstr /n .
like image 25
2 revs Avatar answered Oct 03 '22 08:10

2 revs