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...
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
.