Google
 

Saturday, April 18, 2009

Calling a PowerShell script in a path with a white space from command line

I stuck in this problem once, so here is a solution in case you face it.
First, how to call a script from PowerShell console when the script file path contains white space? because executing this:
PS C:\> c:\new folder\myscript.ps1 param1
will give this error:
The term 'c:\new' is not recognized as a cmdlet, function, operable program, or script file. Verify the term and try again.

Putting the path between quotations like this:
PS C:\> "c:\new folder\myscript.ps1" param1
Will lead to:
Unexpected token 'param1' in expression or statement.

And the solution is to use the Invoke Operator "&", which is used to run script blocks
PS C:\> & 'c:\new folder\myscript.ps1' param1

So farm so good. Now coming to the next part which is calling this from command line.
Executing a PowerShell script from command line is as easy as:
C:\Documents and Settings\Hesham>powershell c:\MyScript.ps1 param1

This is fine as long as the script path has no spaces. For example, executing:
C:\Documents and Settings\Hesham>powershell c:\new folder\MyScript.ps1 param1
Again gives:
The term 'c:\new' is not recognized as a cmdlet, function, operable program, or script file. Verify the term and try again.


With the help of PowerShell -?, here is a solution:
C:\Documents and Settings\Hesham>powershell -command "& {&'c:\new folder\MyScript.ps1' param1}"

Tada!!

16 comments:

alex o. said...

Thanks for the tip!

Your suggestion to use & helped me to solve a problem: when loading a function body that contains quotes from a .ps1 file I'd always get a parse error "Unexpected Token" for anything immediately after the closing quote. Putting the & in front of the quoted path solved this problem.

BTW, another method of invoking scripts with spaces in their paths is by escaping just the space character alone like this (note the tick character before the space):

c:\new` folder\myscript.ps1 param1

Hesham A. Amin said...

Thanks alex o., the method you mentioned works great too.
Can you post an example of how using & solved your issue?

Anonymous said...

Hello,
Just wanted to show how we can take this to the next level if the parameter itself you are passing to your script contains a space. Here is an example where a registry key (with spaces) is passed as a parameter to a Powershell script.

Calling it from a batch file
Powershell -noexit -command "&{&'C:\PS\SKRemoteRegistry.ps1' SERVERNAME 'HKCU\Control Panel\International'}"

Your comments helped me get to this final conclusion. Thanks !
SK

Bryan said...

The Powershell team went out of their way to make things consistent and discoverable inside of the PS shell. But could they have possibly made this aspect any more confusing and difficult to figure out?

At any rate, I think you profusely for posting these solutions to the problem of calling scripts with spaces in the path and passing in arguments with spaces.

Anonymous said...

Really helpful. I was struggling to fix. The post made me happy to fix.

Anonymous said...

I have got space characters not in file path but in Azure Subscription name (Windows Azure MSDN Subscription), my command is like this:

C:\file.ps1 -subscriptionName "Windows Azure MSDN Subscription"
This does not fail but does not shows the correct subscriptioname when I do an Write-Output

Using your method:

C:\file.ps1 -subscriptionName "& 'Windows Azure MSDN Subscription'"

This fails with message - 'Ampersand not allowed. The & operator is reserved for future use; use "&" to pass ampersand as a string.'

Can you please help me find a solution to this.

Hesham A. Amin said...

@Anonymous:
Create a simple ps1 file like this:

param ([string] $subscriptionName)
Write-Output $subscriptionName

Save it as test.ps1 and run (from PowerShell prompt not CMD):
.\test.ps1 -subscriptionName "Windows Azure MSDN Subscription"

The output is:
Windows Azure MSDN Subscription

So it should work. How does your script look like and what is the output you get?

Anonymous said...

Hi,

my function is:

function Expand-ZIPFile($file, $destination)
{
$shell = new-object -com shell.application
$zip = $shell.NameSpace($file)
foreach($item in $zip.items())
{
$shell.Namespace($destination).copyhere($item)
}
}

And I am able to execute it using

Expand-ZIPFile –File “E:\AE\MYDOC.zip” –Destination “E:\AE\New MYDOC”

in powershell.

I have tried your suggested methods to call it using cmd. But not able to do successfully. Please help me.

Hesham A. Amin said...

@Anonymous:
You need to create a PowerShell file (.ps1) and place that code inside it without the function definition as I've shown in a previous comment.
It should look like:

param ([string] $file, [string] $destination)
$shell = new-object -com shell.application
$zip = $shell.NameSpace($file)
foreach($item in $zip.items())
{
$shell.Namespace($destination).copyhere($item)
}
and save it as Expand-ZIPFile.ps1

And invoke it from command line using:
Powershell c:\Expand-ZIPFile.ps1 –File “E:\AE\MYDOC.zip” –Destination “E:\AE\New MYDOC”

The point is that the function you created is not "visible" outside PowerShell.

S├ębastien Sougnez said...

Thanks!

newclique said...

Far simpler way: Put the ` character in front of the spaces like so:
Run` My` Script.ps1

polina Drowpathi devi said...

I am not able to achieve the same when I do it from WinForms can you help me

Hesham A. Amin said...

@polina Drowpathi devi
Can you describe the specific problem you're facing?

Kanishk Singh said...

Hey Hesham! Thanks for this solution.

I'm trying to run this:
powershell -Command "&{&'filebot -script fn:amc --output' "E:/" '--action move --conflict skip -non-strict' "E:/New" '--log-file' amc.log '--def' "seriesFormat=/TV Shows/{n}/{'Season '+s}/{s00e00} - {t }" '--def' "exec=@E:/New/config/args.txt}" ; "& {&'.\FileProcessor.py'}"

But I get an error:
--------------------------
At line:1 char:160
+ ... -file' amc.log '--def' seriesFormat=/TV Shows/{n}/{'Season '+s}/{s00e ...
+ ~
You must provide a value expression following the '+' operator.
At line:1 char:160
+ ... file' amc.log '--def' seriesFormat=/TV Shows/{n}/{'Season '+s}/{s00e0 ...
+ ~
Unexpected token 's' in expression or statement.
+ CategoryInfo : ParserError: (:) [], ParentContainsErrorRecordException
+ FullyQualifiedErrorId : ExpectedValueExpression
--------------------------

As you can see, it's getting stuck at "/{'Season '+s}" which is meant to concatenate the word "season" with the number "s" resolves to.

How can I avoid this?

Hesham A. Amin said...

@Kanishk Singh
I'm not sure I quite understand the logic of your script. But generally powershell variables must start with $. so 's' is not a valid variable name.

Kanishk Singh said...

It's a variable used by Filebot program.

Anyway, by a series of trial and error I was able to make it work. The values of parameters also need to be enclosed in single quotes, I didn't realized that. And I solved the {"Season "+s} issue by enclosing the word "SEASON" in two single quotes -> {''Season''+s}.

This was the final script I ended up using:

powershell -Command "&{&'filebot.launcher' -script fn:amc --output '"E:\\"' --action 'move' --conflict 'auto' -non-strict --log-file 'amc.log' --def unsorted=y subtitles=en clean=y '"ut_dir=%F"' '"ut_kind=multi"' '"ut_title=%N"' '"ut_label=%L"' '"seriesFormat=E:\TV Shows\{n}\{''Season ''+s}\{s00e00} - {t}"' '"exec=@E:\New\config\args.txt"'}"; "&{&'E:\New\config\FileProcessor.py'}"