6

A while back I asked about Batch Script Redirection Syntax and received a nice answer. I've utilized the parenthesis () method more often to echo in batch scripts and redirect to files, etc.

I've run into an odd issue where it appears the word Where is not be able to be echo'd as that word literally and it seems it's interpreted as the Where command being invoked instead.


To keep this example simple, I've dumbed down the script logic to a much simpler version, but the PowerShell logic being echo'd could be much more complex than this.

Script Example

@ECHO ON

(
    ECHO [System.IO.DriveInfo]::GetDrives() ^| Where {$_.Name -like "C:\"}
)>> Outfile.txt

PAUSE

Error

INFO: Could not find files for the given pattern(s).

enter image description here


What I've done

I troubleshot this a little and did some quick research and couldn't find a simple answer. Since I have not asked many questions on SuperUser, I figured this would be a good one potentially.

One thing in particular I tried was setting a variable as a string value of Where (i.e. SET w=Where) and then in the parenthesized echo commands I referenced that variable (i.e. %w%) in place of the word Where but the result is still the same error.

I also played around a little with SETLOCAL ENABLEDELAYEDEXPANSION but it made no difference.

@ECHO ON
SET w=Where
(
    ECHO [System.IO.DriveInfo]::GetDrives() ^| %w% {$_.Name -like "C:\"}
)>> Outfile.txt
PAUSE

The Workaround

I have simply not been using the parenthesized method for echoing the word "Where" and I have just been utilizing the appended >> redirect to the file method on each echo'd line individually where "where" is involved. No big deal for this small example but a bigger deal for a larger script.

@ECHO ON
ECHO [System.IO.DriveInfo]::GetDrives() ^| Where {$_.Name -like "C:\"}>> Outfile.txt
PAUSE

Correlated Questions

Hmmmmm......

  1. What is causing this and what exactly is happening when this occurs?

  2. Is there a way to allow the word (or string) "Where" to be used without the issue?


Resources

4

You have misdiagnosed the problem - WHERE has nothing to do with it.

You simply need to escape the closing parenthesis:

@ECHO ON

(
    ECHO [System.IO.DriveInfo]::GetDrives(^) ^| Where {$_.Name -like "C:\"}
)>> Outfile.txt

PAUSE
  • 3
    Actually, where is not completely irrelevant: it was where.exe that generated the error message INFO: Could not find .... In other words, because of the questioner's syntax, where was taken as a command, rather than a clause. – AFH Oct 23 '17 at 13:16
  • 1
    @AFH - Interesting point. But I am a bit puzzled as to why where.exe is executing. I expected a syntax error because there was no & after the ). But some how the escaped | is allowing Where to be interpreted as a command. – dbenham Oct 23 '17 at 15:01
  • 3
    @AFH - I've started a discussion about this oddity at dostips.com/forum/viewtopic.php?f=3&t=8198 – dbenham Oct 23 '17 at 18:25
  • 1
    @ITSnuggles - There are two separate issues here. The fundamental problem was the unescaped ). Unless you are a batch geek like me, that is all you need worry about. The other obscure issue (a newly discovered quirk) is you cannot escape a special character token like | immediately following closure of a parenthesized block. That shouldn't be an issue because I'm not aware of any valid syntax that uses an escaped token after closure. But the behavior violates our current understanding of batch parsing rules. (Continued in next comment) – dbenham Dec 25 '17 at 14:28
  • 1
    I started a dostips discussion about this new discovery, and PenPen was simply advancing a theory as to a possible flawed internal design of cmd.exe that might explain the source of the obscure behavior. I cannot follow the logic of his theory enough to draw any conclusion. – dbenham Dec 25 '17 at 14:34
3

Here is one other option for you. This doesn't require you to escape the parentheses or the pipe. When you redirect the NUL device to the SET /P command it writes the prompt string to stdout. The one caveat to this is that SET /P doesn't write out a carriage return and line feed so you need an empty ECHO. to output the CRLF.

@ECHO OFF

(
<nul set /p "=[System.IO.DriveInfo]::GetDrives() | Where {$_.Name -like "C:\"}" &echo.
echo another line
)>Outfile.txt

notepad Outfile.txt
PAUSE
2

For what it’s worth, it seems that, after a ), CMD interprets ^| as |:

C:\> (echo 1.The && echo 2.quick && echo 3.brown && echo 4.fox) ^| find "q"
2.quick

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.