PowerShell : 스크립트 디렉토리에서 명령 실행


144

스크립트의 현재 디렉토리를 사용하여 몇 가지 작업을 수행하는 PowerShell 스크립트가 있습니다. 따라서 해당 디렉토리 내부에서 실행 .\script.ps1이 올바르게 작동합니다.

이제 스크립트의 참조 디렉토리를 변경하지 않고 다른 디렉토리에서 해당 스크립트를 호출하려고합니다. 그래서 전화를 걸고 ..\..\dir\script.ps1그 스크립트가 디렉토리 내부에서 호출 된 것처럼 동작하기를 원합니다.

이를 수행하는 방법 또는 스크립트를 수정하여 모든 디렉토리에서 실행할 수 있습니까?

답변:


200

스크립트 옆에 파일을 참조 할 수 있도록 스크립트 자체 경로를 원하십니까? 이 시도:

$scriptpath = $MyInvocation.MyCommand.Path
$dir = Split-Path $scriptpath
Write-host "My directory is $dir"

$ MyInvocation 및 해당 속성에서 많은 정보를 얻을 수 있습니다.

현재 작업 디렉토리에서 파일을 참조하려면 Resolve-Path 또는 Get-ChildItem을 사용할 수 있습니다.

$filepath = Resolve-Path "somefile.txt"

편집 (OP의 의견을 기반으로 함) :

# temporarily change to the correct folder
Push-Location $folder

# do stuff, call ant, etc

# now back to previous directory
Pop-Location

Invoke-Command를 사용하여 비슷한 것을 달성하는 다른 방법이있을 수 있습니다.


1
흠, 아마도 내 스크립트에 대해 좀 더 분명했을 것입니다. 실제로 ant일부 매개 변수를 사용하여 호출하는 스크립트입니다 . 따라서 ant구성 파일을 올바르게 찾을 수 있도록 해당 폴더에서 호출 해야합니다. 이상적으로는 해당 스크립트 내에서 로컬로 실행 디렉토리를 임시로 변경할 무언가를 찾고 있습니다.
찌를

3
아, 그 경우에 당신이 원하는 것 Push-LocationPop-Location
JohnL

5
그주의, $ MyInvocation는 상황에 맞는, 내가 평소에 $ SCRIPTPATH = (GET-변수 MyInvocation - 범위 스크립트) 중첩 또는 기능을 모든 종류의에서 작동 .Value.MyCommand.Path

39

기본 앱을 호출하는 경우 [Environment]::CurrentDirectoryPowerShell의 $PWD현재 디렉토리에 대해 걱정 하지 않아도됩니다 . 여러 가지 이유로, PowerShell은 Set-Location 또는 Push-Location을 수행 할 때 프로세스의 현재 작업 디렉터리를 설정하지 않으므로 설정 될 것으로 예상되는 응용 프로그램 (또는 cmdlet)을 실행중인 경우 그렇게해야합니다.

스크립트에서 다음을 수행 할 수 있습니다.

$CWD = [Environment]::CurrentDirectory

Push-Location $MyInvocation.MyCommand.Path
[Environment]::CurrentDirectory = $PWD
##  Your script code calling a native executable
Pop-Location

# Consider whether you really want to set it back:
# What if another runspace has set it in-between calls?
[Environment]::CurrentDirectory = $CWD

이것에 대한 완벽한 대안은 없습니다. 우리의 대부분은 세트에 우리의 프롬프트 기능에서 [환경] ::은 CurrentDirectory을 라인을 넣어 ...하지만 당신이 위치를 변경하는 때 당신을 도움이되지 않습니다 내에서 스크립트를.

이것이 PowerShell에 의해 자동으로 설정되지 않는 이유에 대한 두 가지 참고 사항 :

  1. PowerShell은 다중 스레드 일 수 있습니다. 단일 프로세스 내에서 여러 Runspace (RunspacePool 및 PSThreadJob 모듈 참조)를 동시에 실행할 수 있습니다. 각 실행 영역에는 고유 한 $PWD현재 작업 디렉토리가 있지만 하나의 프로세스와 하나의 환경 만 있습니다.
  2. 단일 스레드 인 $PWD경우에도 항상 유효한 CurrentDirectory가 아닙니다 (예 : 레지스트리 공급자에 CD를 넣을 수 있음).

프롬프트에 넣으려면 (단일 스레드의 주 실행 영역에서만 실행) 다음을 사용해야합니다.

[Environment]::CurrentDirectory = Get-Location -PSProvider FileSystem

4
경로 제공자 때문에 프로세스 작업 디렉토리를 변경하지 않습니다. 레지스트리, SQL 데이터베이스 또는 IIS 하이브 등에 CD를 넣을 수 있습니다.
piers7

1
예. 나는 그것이 마지막 "최종 메모"의 요점임을 알고있다. 프롬프트 기능에서와 마찬가지로 세계의 다른 모든 쉘과 마찬가지로 FileSystem 제공자의 현재 위치로 업데이트 할 수 있습니다.
Jaykul

2
거룩한 스크립팅 신들, 나는 너무 실망 .\_/.했다.이 때문에 내 하루 반이 죽었다. 사람들 이요? 심각하게? ..
ulidtko

2
이제는 대부분 불필요하며, 최신 버전의 PowerShell은 바이너리 앱을 시작할 때 작업 디렉토리를 설정합니다.
Jaykul

1
이 방법은와 [Environment]::CurrentDirectory다를 경우 원본을 복원 할 수 없습니다 $PWD. 올바른 방법은 변수에 변수를 저장 $origEnvDir = [Environment]::CurrentDirectory한 다음 나중에 복원하는 것 [Environment]::CurrentDirectory = $origEnvDir입니다.
Strom

37

투표 수가 많은 답변이 있지만 질문을 읽을 때 스크립트가 실행되는 디렉토리가 아니라 스크립트가있는 디렉토리를 알고 싶다고 생각했습니다. powershell의 자동 변수를 사용하여 정보를 얻을 수 있습니다

$PSScriptRoot - the directory where the script exists, not the target directory the script is running in
$PSCommandPath - the full path of the script

예를 들어 Visual Studio 솔루션 파일을 찾아 시작하는 $ profile 스크립트가 있습니다. 솔루션 파일이 시작되면 전체 경로를 저장하고 싶었습니다. 그러나 원본 스크립트가 존재하는 곳에 파일을 저장하고 싶었습니다. 그래서 $ PsScriptRoot를 사용했습니다.


12

필자는 종종 다음 코드를 사용하여 실행중인 스크립트와 동일한 디렉토리에있는 모듈을 가져 왔습니다. 먼저 powershell이 ​​실행되는 디렉토리를 가져옵니다.

$ currentPath = 분할 경로 ((Get-Variable MyInvocation -Scope 0) .Value) .MyCommand.Path

가져 오기 모듈 "$ currentPath \ sqlps.ps1"


당신은 스크립트로 - 범위를 설정할

9

이것은 잘 작동합니다.

Push-Location $PSScriptRoot

Write-Host CurrentDirectory $CurDir

Pop-Location경로를 원래 상태로 되돌리려면 끝에 전화하는 것을 잊지 마십시오 .
Lam Le

2

CLI에서 스크립트를 사용하지 않고 잠시 동안이 솔루션을 찾고있었습니다. 이것이 내가 xD를 수행하는 방법입니다.

  • 스크립트를 실행할 폴더로 이동하십시오 (중요한 것은 탭 완성이 있다는 것입니다)

    ..\..\dir

  • 이제 큰 따옴표로 위치를 둘러싸고 그 안에 add을 추가 cd하여 다른 powershell 인스턴스를 호출 할 수 있습니다.

    "cd ..\..\dir"

  • ;powershell의 명령 구분 기호를 사용하여으로 구분 된 스크립트를 실행하려면 다른 명령을 추가하십시오.

    "cd ..\..\dir\; script.ps1"

  • 마지막으로 powershell의 다른 인스턴스로 실행하십시오.

    start powershell "cd..\..\dir\; script.ps1"

그러면 새로운 powershell 창이 열리고으로 이동하여 창을 닫고 ..\..\dir실행 script.ps1합니다.


";" 명령을 하나씩 입력 한 것처럼 첫 번째로 실패하면 두 번째로 실행되고 다음에 다음에 다음에 다음 명령이 분리됩니다. 먼저 원하는 폴더로 이동하여 탭 완성을 사용할 수 있습니다 (큰 따옴표는 사용할 수 없음).

start powershell "-noexit cd..\..\dir\; script.ps1"

큰 따옴표를 사용 ""하여 이름에 공백이있는 디렉토리를 전달할 수 있습니다.

start powershell "-noexit cd '..\..\my dir'; script.ps1"


0

@JohnL의 솔루션에서 하나의 라이너를 만들었습니다.

$MyInvocation.MyCommand.Path | Split-Path | Push-Location
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.