1

Im trying to execute this piped command:

powershell.exe Get-ChildItem | Where-Object { $\_.Name -match "router" } 

in GnuProlog:

:- initialization(main).

main :-
    shell('powershell.exe Get-ChildItem \174\ Where-Object { $_.Name -match "router" }'), nl, halt.

It seems that shell predicate does not support piping, since the output is:

'Where-Object' is not recognized as an internal or external command, operable program or batch file.
warning: C:/prolog.pl:1: user directive failed

is there another way to do it?

odium
  • 21
  • 2
  • Does prolog _not_ let you invoke a command with a list of arguments instead of a single string? Far more control if you can do it the list way instead of needing to make your code be successfully passed through a first shell (to split the string into words and assemble those into a command, then run that command) before it reaches the second. – Charles Duffy Feb 03 '23 at 21:47
  • (mind, if you're on Windows, then there are no-first-shell ways to invoke a program that _still_ starting from a string, but... you haven't specified if you're on Windows, and it's not clear from the question; powershell _is_ available cross-platform) – Charles Duffy Feb 03 '23 at 21:48
  • 1
    @CharlesDuffy cross platform PowerShell has the executable name `pwsh` or `pwsh.exe` rather than `powershell.exe`. SWI Prolog has [process_create/3](https://www.swi-prolog.org/pldoc/man?predicate=process_create/3) which lets you pass an argumnet list and gives you stdin/stdout access to interact with it. From what I can Google, GNU Prolog only works on Windows inside Cygwin, so I'd be surprised if it supports much Windows specific API calls, but I haven't used it so maybe it does. – TessellatingHeckler Feb 03 '23 at 22:05
  • (Reading that process_create doc; "*on Windows, the arguments are simply concatenated to form the commandline*" so it might not help here). – TessellatingHeckler Feb 03 '23 at 22:06
  • Hm. If it's a Cygwin build _of GNU Prolog_, the "on Windows" provisios won't necessarily apply; Cygwin will _try_ to do escaping equivalent that Microsoft's libc implementation will reverse effectively when passed a list. But... if they _only_ support Windows through Cygwin and have that documentation, then perhaps they aren't _letting_ Cygwin do the right thing for them and are instead trying to be "smart". – Charles Duffy Feb 03 '23 at 22:08

1 Answers1

0

I think you need to quote the whole argument in double quotes for Windows' system call handler to see it as one thing. And then edit the other quotes in it so they don't clash with either the Prolog atom single quotes or the PowerShell argument double quotes.

Try:

shell('powershell.exe -NoProfile -NonInteractive -Command "Get-ChildItem | Where-Object { $_.Name -match \'router\' }"'), nl, halt.

You might be able to skip the complexity of piping to Where-Object with:

Get-ChildItem -Filter *router*

PowerShell supports having the command code sent to it in Base64 encoded UTF16-LE, using the -EncodedCommand parameter; that exists to solve this kind of problem, and the effort of carefully quoting and escaping for shell handlers.

TessellatingHeckler
  • 27,511
  • 4
  • 48
  • 87
  • 1
    Yes the double quotes on the powershell arguments worked! Usually every other language i did the same thing handles the command (invoking the shell + the arguments) as one big string! thanks!! – odium Feb 03 '23 at 22:05