powershell - scripts - ¿Cómo puedo encontrar la ruta de origen de un script de ejecución?
powershell script (7)
Esta pregunta ya tiene una respuesta aquí:
Quiero poder decir de qué ruta se ejecutó mi script de ejecución.
Esto a menudo no será $ pwd.
Necesito llamar a otras secuencias de comandos que están en una estructura de carpetas relativa a mi secuencia de comandos y aunque pude codificar las rutas, eso es tan desagradable como un poco doloroso cuando intento pasar de "dev" a "prueba" a "producción".
Creo que puedes encontrar la ruta de tu script en ejecución usando
$MyInvocation.MyCommand.Path
Espero eso ayude !
Cédric
Esta es una de esas rarezas (en mi opinión al menos) en PS. Estoy seguro de que hay una buena razón para ello, pero todavía me parece extraño. Asi que:
Si está en un script pero no en una función, $ myInvocation.InvocationName le dará la ruta completa, incluido el nombre del script. Si está en una secuencia de comandos y dentro de una función, $ myInvocation.ScriptName le proporcionará lo mismo.
Etiquetaste tu pregunta para Powershell versión 1.0; sin embargo, si tienes acceso a la versión 3.0 de Powershell, tienes $PSCommandPath
y $PSScriptRoot
que hace que la ruta del script sea un poco más fácil. Consulte la sección "OTRAS FUNCIONES DE SCRIPT" en esta página para obtener más información.
Gracias msorens! Esto realmente me ayudó con mi módulo personalizado. En caso de que alguien esté interesado en hacer su propia cuenta, así es como está estructurada la mía.
MyModule (folder)
- MyModule.psd1 (help New-ModuleManifest)
- MyScriptFile.ps1 (ps1 files are easy to test)
A continuación, hace referencia a MyScriptFile.ps1 en MyModule.psd1. Hacer referencia a .ps1 en la matriz NestedModules colocará las funciones en el estado de sesión del módulo en lugar del estado de la sesión global. ( Cómo escribir un manifiesto de módulo )
NestedModules = @(''./MyScriptFile.ps1'',''./MyOtherScriptFile.ps1'')
Contenido de MyScriptFile.ps1
function Get-ScriptDirectory {
Split-Path $script:MyInvocation.MyCommand.Path
}
try {
Export-ModuleMember -Function "*-*"
}
catch{}
El try / catch oculta el error de Export-ModuleMember al ejecutar MyScriptFile.ps1
Copie el directorio MyModule a una de las rutas que se encuentran aquí $ env: PSModulePath
PS C:/>Import-Module MyModule
PS C:/>Get-Command -Module MyModule
CommandType Name ModuleName
----------- ---- ----------
Function Get-ScriptDirectory MyModule
Hemos estado usando un código como este en la mayoría de nuestros scripts durante varios años sin problemas:
#--------------------------------------------------------------------
# Dot source support scripts
#--------------------------------------------------------------------
$ScriptPath = $MyInvocation.MyCommand.Path
$ScriptDir = Split-Path -Parent $ScriptPath
. $ScriptDir/BuildVars.ps1
. $ScriptDir/LibraryBuildUtils.ps1
. $ScriptDir/BuildReportUtils.ps1
La secuencia de comandos ubicua publicada originalmente por Jeffrey Snover del equipo de PowerShell (incluida en la respuesta de Skyler ) y las variaciones publicadas por Keith Cedirc y EBGreen, todas adolecen de un serio inconveniente: si el código informa lo que espera depende de dónde lo llame. !
Mi código a continuación supera este problema simplemente al hacer referencia al ámbito del script en lugar del ámbito principal :
function Get-ScriptDirectory
{
Split-Path $script:MyInvocation.MyCommand.Path
}
Para ilustrar el problema, creé un vehículo de prueba que evalúa la expresión objetivo de cuatro maneras diferentes. (Los términos entre corchetes son las claves de la siguiente tabla de resultados).
- código en línea [en línea]
- función en línea, es decir, función en el programa principal [función en línea]
- Función de origen de punto, es decir, la misma función se movió a un archivo .ps1 separado [fuente de punto]
- Función de módulo, es decir, la misma función se movió a un archivo .psm1 separado [módulo]
Las últimas dos columnas muestran el resultado del uso del alcance del script (es decir, $ script :) o con el ámbito principal (con -scope 1). Un resultado de "script" significa que la invocación informó correctamente la ubicación del script. El resultado del "módulo" significa que la invocación informó la ubicación del módulo que contiene la función en lugar del script que llamó a la función; esto indica un inconveniente de ambas funciones que no puede poner la función en un módulo.
Dejando a un lado la cuestión del módulo, la notable observación de la tabla es que el enfoque del alcance principal falla la mayor parte del tiempo (de hecho, el doble de veces que tiene éxito).
Finalmente, aquí está el vehículo de prueba:
function DoubleNested()
{
"=== DOUBLE NESTED ==="
NestCall
}
function NestCall()
{
"=== NESTED ==="
"top level:"
Split-Path $script:MyInvocation.MyCommand.Path
#$foo = (Get-Variable MyInvocation -Scope 1).Value
#Split-Path $foo.MyCommand.Path
"immediate func call"
Get-ScriptDirectory1
"dot-source call"
Get-ScriptDirectory2
"module call"
Get-ScriptDirectory3
}
function Get-ScriptDirectory1
{
Split-Path $script:MyInvocation.MyCommand.Path
# $Invocation = (Get-Variable MyInvocation -Scope 1).Value
# Split-Path $Invocation.MyCommand.Path
}
. ./ScriptDirFinder.ps1
Import-Module ScriptDirFinder -force
"top level:"
Split-Path $script:MyInvocation.MyCommand.Path
#$foo = (Get-Variable MyInvocation -Scope 1).Value
#Split-Path $foo.MyCommand.Path
"immediate func call"
Get-ScriptDirectory1
"dot-source call"
Get-ScriptDirectory2
"module call"
Get-ScriptDirectory3
NestCall
DoubleNested
Contenido de ScriptDirFinder.ps1:
function Get-ScriptDirectory2
{
Split-Path $script:MyInvocation.MyCommand.Path
# $Invocation = (Get-Variable MyInvocation -Scope 1).Value
# Split-Path $Invocation.MyCommand.Path
}
Contenido de ScriptDirFinder.psm1:
function Get-ScriptDirectory3
{
Split-Path $script:MyInvocation.MyCommand.Path
# $Invocation = (Get-Variable MyInvocation -Scope 1).Value
# Split-Path $Invocation.MyCommand.Path
}
No estoy familiarizado con lo que se introdujo en PowerShell 2, pero podría ser que el alcance del script no existiera en PowerShell 1, cuando Jeffrey Snover publicó su ejemplo.
Me sorprendió cuando, aunque encontré que su ejemplo de código proliferaba ampliamente en la web, ¡falló inmediatamente cuando lo probé! Pero eso fue porque lo utilicé de forma diferente al ejemplo de Snover (lo llamé no a la parte superior de la secuencia de comandos sino desde dentro de otra función (mi ejemplo "dos veces anidado").)
2011.09.12 Actualización
Puede leer sobre esto con otros consejos y trucos en los módulos en mi artículo recién publicado en Simple-Talk.com: Más allá del agujero del conejo: módulos de PowerShell y encapsulación .
Me encontré con el mismo problema recientemente. El siguiente artículo me ayudó a resolver el problema: http://blogs.msdn.com/powershell/archive/2007/06/19/get-scriptdirectory.aspx
Si no está interesado en cómo funciona, aquí está todo el código que necesita según el artículo:
function Get-ScriptDirectory
{
$Invocation = (Get-Variable MyInvocation -Scope 1).Value
Split-Path $Invocation.MyCommand.Path
}
Y luego obtienes el camino simplemente haciendo:
$path = Get-ScriptDirectory