1

I'm trying to call a powershell script from a batch file.

I have the following

for /F "usebackq delims=" %%a in (
    'PowerShell.exe -ExecutionPolicy ByPass -Command "(@(Select-String %QUERY% %FILE% -Context 0, 1 | % {$_.Context.PostContext} ))"'
) do set RESULT=%%a

echo %RESULT%

But the %RESULT% is printing the whole command not the result.

All I'm trying to do is read a file for a flag and then return the next line as the %RESULT%

I ran the following from command line

PowerShell.exe -ExecutionPolicy ByPass -Command "& (Select-String FAILED e:\path\to\app.log -Context 0, 1 | % {$_.Context.PostContext} )"

and got this

& : The term ':generic/generic.k4.csv' is not recognized as the name of a cmdlet, function, script file, or operable program. Check the spelling of
the name, or if a path was included, verify that the path is correct and try again.
At line:1 char:3
+ & (Select-String FAILED e:\path\to\app.log -Context 0 ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : ObjectNotFound: (:generic/generic.k4.csv:String) [], CommandNotFoundException
    + FullyQualifiedErrorId : CommandNotFoundException
whoisearth
  • 4,080
  • 13
  • 62
  • 130

1 Answers1

2

The problem in your first block of code is the use of the usebackq token, while still wrapping the command in single quotes, forcing the command to be interpreted as a literal string (which is then being put into %RESULT%). From for /?

usebackq - specifies that the new semantics are in force, where a back quoted string is executed as a command and a single quoted string is a literal string command and allows the use of double quotes to quote file names in file-set.

To fix this, either wrap the command in backticks (`) instead of single quotes ('), or remove the usebackq token from your command.

The second PowerShell block does not do the same thing as the first. The syntax & (expr) evaluates the expression inside the parentheses and then tries to execute it. In this case, your Select-String is being evaluated, and returning the selected line. PowerShell is trying to execute the extracted line as if it's a command. This is probably not what you want.

For further analysis, please provide more explanation about what you expected to happen here, along with an example of the contents of app.log.

Ryan Bemrose
  • 9,018
  • 1
  • 41
  • 54
  • 1
    He's also got to escape the pipe with `^|`. – SomethingDark May 17 '16 at 04:36
  • @SomethingDark Normally I'd agree, but when I ran the command it executed correctly without escaping the pipe. ¯\\_(ツ)_/¯ – Ryan Bemrose May 17 '16 at 04:48
  • I've been [rebuked before](http://stackoverflow.com/questions/35962454/35962630#comment59585741_35962630) for suggesting somebody escape a character that wasn't strictly required by the parser, so I'm not about to suggest it again unless I'm certain the code won't work without it. – Ryan Bemrose May 17 '16 at 04:50
  • Weird; pipes usually break `for` loops. Must be because it's inside quotes with `usebackq`. – SomethingDark May 17 '16 at 04:55
  • 1
    @SomethingDark - From a CMD.EXE FOR /F perspective, the pipe must be either quoted, or escaped, but not both. The pipe is within a quoted string, so it should not be escaped. – dbenham May 17 '16 at 11:58
  • ... but the single percent-sign in this part: `-Context 0, 1 | % {$_.Context.PostContext}` must be doubled this way: `-Context 0, 1 | %% {$_.Context.PostContext}` – Aacini May 17 '16 at 14:07
  • Good catch, @Aacini. I think it's better in this case to change the percent sign to the PS keyword `foreach`, which is more explicit and doesn't have any issues with escaping. – Ryan Bemrose May 17 '16 at 16:29