2

See the below script that I have for renaming Movie files with .mp4 or .mkv extensions:

<# ::

@echo off
powershell -c "iex ((Get-Content -LiteralPath '%~f0') -join [Environment]::Newline); iex 'main %*'"
pause && goto :eof
#>

$path = Split-Path -Path $PSScriptRoot -Parent
echo $path
## $validExtensions = '.mkv', '.mp4'
## Get-ChildItem -LiteralPath $path -File |
##     Where-Object Extension -In $validExtensions |
##     Where-Object Length -GT 500mb |
##     Rename-Item -NewName {
##         ($_.BaseName -replace 'MkvHub.com - ' -replace '(?<=1080p|720p).+' -replace '\.', ' ').ToUpper() + $_.Extension
##     }

Currently I have commented out the rest of the Powershell code for obvious reason of testing whether the code Split-Path -Path $PSScriptRoot -Parent or split-path $myInvocation.myCommand.path would give us the literal path of this same script during execution or not.

Clearly it doesn't give me the expected path, and instead throws this error:

Split-Path : Cannot bind argument to parameter 'Path' because it is an empty string.
At line:7 char:26
+ $path = Split-Path -Path $PSScriptRoot -Parent
+                          ~~~~~~~~~~~~~
    + CategoryInfo          : InvalidData: (:) [Split-Path], ParameterBindingValidationException
    + FullyQualifiedErrorId : ParameterArgumentValidationErrorEmptyStringNotAllowed,Microsoft.PowerShell.Commands.Spli
   tPathCommand

Press any key to continue . . .

Also the similar error with split-path $myInvocation.myCommand.path too.

As aforementioned I already tried both split-path $myInvocation.myCommand.path and Split-Path -Path $PSScriptRoot -Parent, but none of them are working.

Can anyone help figuring this out ? I have to make this work in hybrid script only...

4
  • Is your question/problem that when using this 'hybrid' methodology, $PSScriptRoot does not hold the value of the parent directory of the running batch file? Also, I should mention that %* could include doublequotes, which could cause you issues, as those would be nested within the -c/-command doublequotes. Commented Oct 28, 2023 at 16:04
  • I don't know much about how the $PSScriptRoot is formed when Powershell command/script is invoked, but it seems that it's losing it's value when used inside Hybrid script for sure. Commented Oct 28, 2023 at 16:13
  • Would ensuring your current directory in the batch file was set to the batch file parent not mean that PowerShell inherits it? In that case you could use relative paths or split out from Get-Location. As a somewhat related side question, what is stopping you from using %~dp0/%~p0 from the batch file, and passing it as an argument, or defining it as a variable to be used as needed by PowerShell? Commented Oct 28, 2023 at 17:47
  • 2
    There can be inserted below @echo off the command line setlocal EnableExtensions DisableDelayedExpansion and the command line set "ScriptPath=%~dp0". The string value of the environment variable ScriptPath can be accessed from with the PowerShell script code wherever this directory path is needed in the PowerShell script code. Please note that the directory path assigned to the environment variable ScriptPath ends always with a backslash. Commented Oct 28, 2023 at 17:47

1 Answer 1

1

Fundamentally, the automatic $PSScriptRoot and $PSCommandPath are only defined inside script files (*.ps1) (and script module files (*.psm1)).

Since your hybrid batch-file approach relies on invoking powershell.exe, the Windows PowerShell CLI, by directly passing source code to its -c (-Command) parameter, these variables are therefore not defined.

As Mofi suggests, you can set a variable with the batch file's own directory before calling powershell.exe, which - due to cmd.exe variables also being environment variables - the PowerShell code can then access as such, using the $env: namespace.

However, a robust hybrid batch/PowerShell solution requires the use of the -File PowerShell CLI parameter in order to correctly handle pass-through arguments, which in turn requires creating a temporary copy of the batch file as a .ps1 file.

See this answer, which combines the -File approach with passing the original batch-file path via an environment variable, allowing the PowerShell code to infer the equivalents of $PSScriptRoot and $PSCommandPath.

Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.