Powershell – Running Powershell Scripts embedded within folders that have spaces in their name

Background

This is a stupid problem to have, but I have it.

I created a long folder name that has a space between two words.

 

PowerShell Script

 


#Set-StrictMode
#Establishes and enforces coding rules in expressions, scripts, and script blocks.
#https://technet.microsoft.com/en-us/library/hh849692.aspx
set-strictmode -version 1.0

$user = [Environment]::UserName

$strLog = "Hello {0}" -f $user
Write-Host $strLog

 

Error

Now when I try to run to run a power script, I get an error message:

Syntax:


powershell "c:\hello world\helloworld.ps1"

 

Error Message:

 

IsNotrecognizedAsNameOfACmdlet

Textual:

 


c:\hello : The term 'c:\hello' 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:1
+ c:\hello world\helloworld.ps1
+ ~~~~~~~~
+ CategoryInfo : ObjectNotFound: (c:\hello:String) [], CommandNot
FoundException
+ FullyQualifiedErrorId : CommandNotFoundException

 

Solution

With Single Quotes (does not work)

Script


    set dirCurrent=%CD%

    powershell -Command '%dirCurrent%\helloworld1.ps1'

 

Output:

helloWorldWithSingleQuotes

Explanation:

Nada. No error message.

 

With & (works)

Idea

Let us use the ampersand & and enclose our payload in single quotes

Script


set dirCurrent=%CD%

powershell -Command "& '%dirCurrent%\helloworld.ps1' "

 

Output:

helloWorldWithHypersign

 

 

With %~dpn0 (works)

Concept

Batch files have a special tag (%~dpn0) that allows use to get path (p), name of the calling script (n0)

And, so if we name our command script (helloworld.cmd); notice that both our invoking script and our calling script share the same name; albeit with different extension (.cmd and .ps1 respectively).

 

Script


rem command file and powershell share same file name
rem different extension (.cmd and .ps1) and so we can
rem use %~dpn0
powershell -Command "& '%~dpn0.ps1' "

 

Output:

 

helloWorldWithSpecialTag

 

Command Line Arguments

Similar care occurs when we need to pass in command line arguments and the arguments possibly reference folders \ files with spaces.

Here are the files that we will use for this example.

 

File name Purpose
 sarai.txt  This is a simple text file that we will be reading in.
 readfileContent.ps1  Powershell script that reads text file and prints out its contents.
 readFileContent.cmd  Batch file that invokes powershell script (errors out)
 readFileContentRemediate.cmd  Cleaned-up batch file

 

 

sarai.txt

sarai was here.

 

readFileContent.ps1


param($filename = $(throw "You must specify a file"))
#Set-StrictMode
set-strictmode -version 1.0

[string] $strContent = $null;

$strContent = Get-Content $filename
Write-Host $strContent

readFileContent.cmd


   set dirCurrent=%CD%

   powershell -Command "& '%dirCurrent%\readFileContent.ps1'"  %dirCurrent%\sarai.txt

Output:

Image:

readFileContent

 

Textual:


Get-Content : Cannot find path 'C:\hello' because it does not exist.
At C:\hello world\readFileContent.ps1:9 char:15
+ $strContent = Get-Content $filename
+ ~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : ObjectNotFound: (C:\hello:String) [Get-Content],
ItemNotFoundException
+ FullyQualifiedErrorId : PathNotFound,Microsoft.PowerShell.Commands.GetContentCommand

 

Remediate:

To fix, enclose in single and double-quotes :

readFileContentRevised.cmd


set dirCurrent=%CD%

powershell -Command "& '%dirCurrent%readFileContent.ps1'" "'%dirCurrent%\sarai.txt'"


Quick Explanation
:

  • The Powershell script file name should be prefixed with & and surrounded in double and single quotes
  • Command line arguments that reference files in the folder should be surrounded in double and single quotes; note no need for &, as that is only needed to expand scripts

 

Crediting ss64.com

Here is what make this whole thing work:

 

Call Operator
http://ss64.com/ps/call.html

The call operator (&) allows you to execute a command, script or function.

Many times you can execute a command by just typing its name, but if the command (or the path) contains a space then this will fail.
Putting the command in quotes would make PowerShell treat it as a string, so in addition to quotes, use the call operator to force PowerShell to treat the string as a command to be executed.

Syntax
      & "[path] command" [arguments]

Key:
    command   An executable filename (.exe), script or function.

   arguments  The call operator will only handle a single command.
              Any arguments may follow the called command.

              If the pathname contains spaces, place the command
              inside double quotes and any arguments outside the quotes.

 

Dedicated

Dedicated to the great Dean Smith.

Like they say in Carolina, “If God is not a Carolina fan, why is the sky Carolina Blue“.

Leave a comment