Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does a rem impact a code block that has its output piped?

I love using blocks of commands enclosed in parentheses, as it allows me to pipe the output of all commands in the block to more (or any other command) at once.

Usually, I can add remarks (rem) inside these blocks, too.

However, I cannot seem to combine the two features: a block with remarks piped to more (or any other command) is not executed at all. Why is that? Can it be solved?

@echo off
rem This works (prints X1)
(
    echo X1
)

rem This works (prints X2)
(
    echo X2
) | more

rem This works (prints X3)
(
    rem
    echo X3
)

rem Why does this print nothing?
(
    rem
    echo X4
) | more

rem Or this?
(
    echo X4
    rem
) | more

rem This works (prints X5)
(
    :: Using colons instead of rem
    echo X5
) | more
like image 642
bers Avatar asked Oct 29 '25 01:10

bers


1 Answers

It's because of the folding.
Using pipes results in two separate child cmd.exe processes.
But the code has to be folded before it's transferred to a cmd.exe, especially code blocks.

The folding rule is simple, each new line will be translated into an ampersand.
So a folded block looks like

( echo X1 & echo X2 )

But with a REM you get

( REM & echo X4 ) 

The REM remarks the rest of the line, the ampersand has no effect anymore and the closing parenthesis is also remarked.

If the REM is after that ECHO, it's the same problem

( echo X4 & REM ) 

The last part is remarked, so there is only ( echo X4 and the closing parenthesis is missing.

But why :: comments work?
It looks like :: should result in the same error like REM, but it works!
It's because :: labels are completely stripped from a code block, so the resulting line for a block like

( 
  :: My comment
  echo X4
)

Results in simply:

C:\Windows\system32\cmd.exe  /S /D /c" ( echo X4 )"

How to make REM work in piped blocks?

The simple way is to use REM., but it's no quite a real REM, it can't comment out ampersand or other special characters.

( 
  REM. This is a comment, special characters aren't allowed here
  echo This works
) | more

Or use an extra line feed in the REM line

(set \n=^
%=THIS LINE IS REQUIRED=%
)
( 
  REM This is a comment with & and | %%\n%% BREAK
  echo This works
) | more

How to debug folded blocks?

It's simple with the cmdcmdline pseudo variable

(
  echo Debug %%cmdcmdline%%%
  echo one
  echo two
) | findstr /n "^"

Result:

1:Debug C:\Windows\system32\cmd.exe /S /D /c" ( echo Debug %cmdcmdline% & echo one & echo two )"
2:one
3:two

See also Why does delayed expansion fail when inside a piped block of code?

like image 110
jeb Avatar answered Oct 30 '25 16:10

jeb



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!