본문 바로가기
IT/System Engineering

윈도우 파워쉘 사용을 위한 10가지 팁

by Jany 2012. 4. 6.
반응형

윈도우 파워쉘 사용을 위한 10가지 팁


제공: 한빛 네트워크
저자: Jeff Cogswell, 김현우 역
원문: Top 10 Tips for Using Windows PowerShell

파워쉘은 커맨드 라인을 대체할 마이크로 소프트의 새로운 툴이다. 아직은 베터버전 이지만, 여기서 최신 버전을 무료로 다운로드 받을 수 있다. 우리같이 좀 묵은 사람들은 예전에 한때 DOS를 썼었고, 좀 지나서는 윈도우즈 환경에서 DOS 커맨드 창과 거의 비슷한 CMD.exe를 사용했다. 그러나 파워쉘은 DOS의 업데이트 버전이 아니다. 파워쉘은 MS가 이전에는 제공했던 어떤 커맨드 라인 프롬프트보다 강력한 커맨드라인 시스템이다. 안타깝게도 이 툴을 배우기 전에 해야 할 일이 있다. (역자: 파워쉘 설치와 함께 XP service pack 2.0 이상과 .NET 프레임워크 2.0이 설치되어 있어야 한다.) 툴을 설치하고 살펴본 후에는 아래의 10가지 팁을 읽어보아라. 여러분의 인생을 보다 편안하게 해줄 것이다.

1. 일관성을 기억하라

커맨드는 동사-명사의 형태로 되어있고 파라미터는 a- 로 시작한다는 것을 기억하라. 경로명에는 \ 과 / 을 모두 사용할 수 있다.

파워쉘을 사용하는데 있어 가장 기본이 되는 규칙은 커맨드의 형식이 항상 동일한 형태로 되어있는 것이다. 이러한 특성을 기억하면 커맨드들을 기억하기가 한결 쉬울 것이다.

동사-명사 구조의 예는 다음과 같다.
Set-Date
Write-Debug
Get-Item
Get-WmiObject
각각의 커맨드는 동사와 명사 사이에 하이픈으로 연결된다. 커맨드의 명사는 복수형을 써야 할 것 같은 상황이라도 단수형을 쓴다.
Get-Process
현재 동작 중인 모든 프로세스를 반환한다. (역자: 여러 프로세스를 가져올 것이지만, Get-Processes가 아닌 Get-Process로 사용한다.)

일관성은 커맨드 명에만 해당하는 것은 아니다. 파라메터 역시 일관적이다. DOS나 Unix 세상에서는 커맨드에서 - 나 / 모두 파라메터를 의미했다. 그러나 파워쉘에서는 모든 파라메터는 - 으로 시작한다. 하지만 경로명에서는 / (forward slash) 나 \ (backward slash) 모두 사용될 수 있다. 더 편하다고 느끼는 것을 사용하면 된다. 경로를 조합해야 할 경우가 있다면 내장된 커맨드인 join-path를 다음과 같이 사용하면 된다.
join-path c:\ \temp
결과는 C:\temp 가 된다.

(이것은 두 문자열을 합칠 때 여러분이 중복된 slash를 직접 지우지 않아도 되기 때문에 편리하다.)

2. 유용한 명령어를 기억하라

커맨드 리스트를 보기위해 Get-Command를 사용하고 커맨드의 사용법을 알기위해서는 Get-Help를 써라. 또한 -? 파라미터를 써서 커맨드의 사용법을 알아낼 수 있다. TabExpansion을 사용해라 (그리고 TabExpansion을 대체할 것을 찾아보아라).

새로운 언어를 쓰게 될 때 여러분은 우선 그 어휘를 알려고 할 것이다. 파워쉘 두 번째 배포에서는 129개의 명령어가 포함되었다. 129개는 배우기에 너무 부담스럽고 기억하기 어렵다. 그러나 여러분이 최소한 어떤 명령어가 사용 가능한지 알고 모든 커맨드 리스트를 보고 싶다면 이렇게 입력하라.
Get-Command
그리고 Get-Help가 있는데, Get-Help는 특정한 커맨드의 사용법을 알려준다.
Get-Help Get-Member
는 커맨드 Get-Members에 대한 도움말을 보여준다. 또는 다음과 같이 -? 파라미터를 전달할 수 있다.
Get-Member -?
이 내장 커맨드는 또한 다른 레벨의 설명을 제공한다. 기본 설명은 기초적인 정보를 보여준다. Get-Help에 -detailed를 파라메터로 붙여 상세한 설명을 제공받을 수 있다.
Get-Help Get-Member -detailed
여기에 더욱 보강된 설명을 얻고자 하면 -full을 사용한다.
Get-Help Get-Member -full
대다수의 커맨드들이 상당히 긴데, 우리 컴퓨터 족들은 보통 긴 명령어를 싫어한다. 그래서 파워쉘은 커맨드의 별칭들을 제공한다. 다음과 같은 모든 별칭의 리스트를 볼 수 있다.
PS C:\WINDOWS\system32> Get-Alias

CommandType     Name            Definition
-----------     ----            ----------
Alias           ac              Add-Content
Alias           asnp            Add-PSSnapin
Alias           clc             Clear-Content
Alias           cli             Clear-Item
Alias           clp             Clear-ItemProperty
...
원하는 커맨드를 찾을 때 Tab 키는 특별한 기능을 제공한다. 만약 동사를 기억한다면 동사와 하이픈를 입력하고 Tab을 반복해서 누르면 해당하는 동사로 시작하는 명령어가 자동으로 입력되며 순환한다. 만약 아래와 같이 입력했다면,
Get-
Tab을 눌러보아라. Get-Acl, Get-Alias, Get-AuthenticodeSignature 등등 명령어를 보게 될 것이다. Tab 표현식은 유연한 편이 바람직한데, MS도 이를 알고 있기 때문에 Tab표현식을 수정할 수 있게 하였다. 인터넷에서 PowerShell TabExpansion(Tab과 Expansion사이에 공백을 넣지 말 것)에 대해서 검색해보면 정보를 찾을 수 있을 것이다. 다른 사람들이 이미 Tab 표현식을 작성해 놓은 것이 있는데, 일부는 꽤 유용하다. 그 중에서 필요한 것을 찾아 사용하면 된다. (추가적으로, Get-Content function:TabExpansion을 사용하면 TabExpansion function의 소스를 볼 수 있다.) 여기 필자가 자주 사용하는 몇몇 커맨드를 나열했다. 커맨드를 사용할 때, 아마도 사용할 수 있는 별칭에 대해서도 알고 싶을 것이다..

커맨드 별칭

커맨드 별칭
Copy-Item cpi, cp, copy
ForEach-Object foreach, %
Get-ChildItem dir, ls
Get-Command gcm
Get-Content cat, type
Get-Content gc, type, cat
Get-Help help
Get-Location gl, pwd
Move-Item mi, mv, move
Remove-Item ri, rd, del, rm, rmdir
Rename-Item rni, ren
Set-Location cd, chdir
Where-Object where

Get-Command는 필요한 커맨드를 찾기 위한 파라메터를 지원한다. 이를테면 커맨드에 Format이라는 단어가 들어간 것들을 찾고자 한다면, 다음과 같이 입력한다.
Get-Command *Format*
동사 Format으로 시작되는 커맨드를 찾고싶을 수도 있다 (Format-Table과 같이). 그럴 때는 이렇게 입력한다.
Get-Command -verb Format
동사가 정확히 Format인 커맨드인 명령어를 반환할 것이다. 만약 아래와 같이 입력하면,
Get-Command -verb Form
아무런 결과도 얻지 못할 것이다. 이럴 때는 와일드카드 형식을 쓴다:
Get-Command -verb Form*
유사하게 명사에 대해서도 적용 할 수 있다.
Get-Command -noun Alias
Alias라는 단어가 들어가는 커맨드를 확인할 수 있을 것이다..

간단한 한 문자 별칭이 두 개 있는데, %는 ForEach-Object의 별칭이고 ?는 Where-Object의 별칭이다.

3. 기본 타입과 내장 변수 배우기

기본 타입과 파서가 그것을 어떻게 인지 하는지 배워보자. 정규 표현식을 마스터 하면 여러분 인생이 완전해질 것이다.. 파워쉘 스크립트 언어는 몇 개의 유용한 기본타입을 지원한다. 그리고 그러한 타입의 변수를 생성할 수 있다. 여기에는 문자열, 숫자, 배열과 사전형(Hash나 Map으로도 알려져 있는)이 있다. .NET에서 기본적으로 지원하는 타입은 모두 사용할 수 있다고 보면 된다. (다음 섹션에서 .NET에 대해서 이야기해 보겠다)

커맨드 분석기는 입력하는 내용에 따라 타입을 결정한다. 만약 당신이 다음을 입력하면
5
당신은 숫자형을 선언한 것이다. 변수 이름은 $로 시작하며 숫자를 다음과 같이 저장할 수 있다.
PS C:\> $a = 5
PS C:\> $a
5
PS C:\>
GetType()을 호출하여 내장된 .NET 타입을 알아낼 수 있다.
PS C:\> $a.GetType()
IsPublic IsSerial Name              BaseType
-------- -------- ----              --------
True     True     Int32             System.ValueType
파서는 또한 다른 기본 타입도 알아낼 수 있다. 더블형은 소수점을 이용해 만들어 진다.
PS C:\> $b = 3.1415926
PS C:\> $b
3.1415926
PS C:\> $b.GetType().Name
Double
오늘날의 대다수의 스크립트 언어와 마찬가지로 스트링에 외 따옴표와 겹 따옴표를 모두 사용할 수 있다. 이는 몇몇 문제 상황에 편리한데, 이를테면 스트링에 겹 따옴표가 있으면 스트링 자체는 외 따옴표로 정의한다.
$c = '<span style="border:1px solid none">'
배열을 생성하기 위해서는 단지 항목을 구분하는 콤마를 쓰면 된다.
PS C:\> $d = 1,2,3,"Hello"
PS C:\> $d
1
2
3
Hello
PS C:\> $d.GetType()

IsPublic IsSerial Name                                     BaseType
-------- -------- ----                                     --------
True     True     Object[]                                 System.Array
필요하다면 배열 주위를 괄호로 묶을 수 있다. 이것은 배열 안에 배열을 넣을 때 유용하다.
$e = (1,2,3,(4,5,6))
숫자의 범위는 .. 연산자를 사용하여 다음과 같이 지정할 수 있다.
$f = 1..5
1,2,3,4,5를 포함하는 배열이 생성될 것이다.

사전형을 생성하기 위해서는 @를 다음과 같이 사용한다.:
PS C:\> $myhash = @{ 'one'=1; 'two'=2; 'three'=3 }
PS C:\> $myhash

Name                           Value
----                           -----
two                            2
three                          3
one                            1

PS C:\> $myhash['one']
1
PS C:\> $myhash['four']
PS C:\>
.NET은 강력한 정규 표현식을 지원하기 때문에, 파워쉘 역시 regex 타입을 지원한다. 정규 표현식을 생성하기 위해서는 대괄호([ ]) 안에 regex를 넣고 뒤에 문자열을 덧붙인다. 그러면 -match 연산자를 이용하여 정규 표현식을 사용할 수 있다.

여기 예문이 있다.
PS C:\> $re = [regex]"abc[123]"
PS C:\> "abc1" -match $re
True
PS C:\> "abc4" -match $re
False
PS C:\>
만약 정규 표현식에 익숙치 않다면 지금이 배워야 할 때이다. 다른 프로그래밍 언어도 그렇지만, 정규 표현식을 많이 알수록 파워쉘을 더욱 쉽게 쓸 수 있다. 자주 사용하는 검색엔진으로 가서 "정규 표현식 배우기"라고 입력해봐라. 괜찮은 페이지가 몇 개 나올 것이다. 그렇지만 가장 좋은 자료는 제프리 프리들이 저술한 오렐리의 정규 표현식 완전 해부와 실습(Mastering Regular Expressions) 이다.

이 책은 모든 컴퓨터 프로페셔널들이 읽어야 할 몇 안 되는 필독서다.

쉘은 몇 가지 변수를 기본으로 내장 한다. 여기에 일부를 나열한다.
  • $$: 이전 줄의 마지막 토큰
  • $?: 마지막으로 성공이나 실패 상태
  • $^: 이전 줄의 첫번째 토큰
  • $pshome: 파워쉘이 설치된 디렉터리. 이 변수는 types.ps1xml같이 설정 관련 파일을 조작할 때 편리하다. 예를 들면,
    scite (join-path $pshome types.ps1xml)
    
(Scite는 내가 애용하는 공짜 텍스트 에디터다.)

특정 구문에 의존하지 않는 타입을 원한다면, 파워쉘이 지원하는 바로 가기 타입을 이용하면 된다. 바로 가기 타입은 타입이름을 줄인 것으로 마이크로소프트 파워셀 블로그에 가면 그 리스트를 볼 수 있다. 타입을 배우고 익히는 것은 어렵다고 느낄 수 있다. 특히 커맨드가 생소한 타입의 오브젝트를 반환할 때는 더욱 그럴 것이다. 온라인 도움말을 잘 이해할 수 있다면 이 블로그를 방문해 보자. 모든 오브젝트 타입에 대한 설명을 볼 수 있어 파워쉘 실력을 키우데 많은 도움이 될 것이다.

(만약 이것을 바꾸려거든 파일을 갱신해야 할 것이다. 팁 "개인 환경 설정하기"를 찾아보면 자세한 정보를 얻을 수 있다.) 이것을 변경할 때 어떤 오브젝트 타입에 대한 온라인 도움말도 찾을 수 있을 것이다. 그 기법은 완벽하지도 않고 모든 오브젝트에 대해 통하지도 않지만 대부분의 경우에는 잘 동작한다..

4. .NET 알기

.NET 프레임워크는 파워쉘이 동작하는데 기반이 된다. .NET에 대해 잘 알게 된다면 독자의 파워쉘 내공도 한층 높아질 것이다..

파워쉘을 최대한 잘 사용하려면 .NET 프레임워크와 친해져야 한다. .NET 프레임워크에 대한 모든 설명은 온라인에서 구할 수 있다. .NET문서의 시스템 부분까지 이동해보자. 여기서 Int32, String, Array같은 기본 타입에 대한 설명을 찾아 볼 수 있다.

간단히 말해서 .NET 프레임워크는 파워쉘 작업 중에 사용 할 수 있는 클래스와 타입들의 집합체라고 할 수 있다. 타입을 많이 알아두면 좋다. 타입들의 목록을 보면 해당 오브젝트로 할 수 있는 것을 알 수 있다. 이를테면 시스템 페이지를 클릭하고 스트링을 클릭하면 스트링 클래스의 목록을 얻을 수 있다.

대부분의 커맨드는 .NET 오브젝트(혹은 오브젝트의 집합)을 반환한다. 예를 들어 Get-Date 커맨드는 화면에 현재 날짜와 시간을 출력할 것이다. 하지만 사실은 커맨드가 DateTime이라는 .NET 프레임워크의 타입을 반환한 것이다. 마찬가지로 Get-ChildItem(혹은 별칭인 dir)을 타이핑하면 디렉터리 리스트가 출력되지만 실제로는 .NET 프레임워크의 DirectoryInfo나 FileInfo 오브젝트의 집합을 보는 것이다.

.NET 프레임워크는 거대한 계층으로 구성되어 있으며, 모든 클래스는 Object로부터 파생된다. Object 클래스는 .NET의 모든 클래스에 기본적이며 공통된 기능을 제공한다. 예를 들면 ToString 이라는 함수이다. 이 함수는 오브젝트를 표현할 수 있는 텍스트를 반환한다. 따라서 파워쉘의 어느 객체에 대해서도 이 함수를 호출하여 오브젝트를 표현하는 텍스트를 얻을 수 있다. (사실 정확히 말하자면 파워쉘이 오브젝트를 콘솔에 출력하는 방법을 의미한다)

5. 파이프라인이 텍스트 기반이 아닌 오브젝트 기반이라는 것을 이해하라

오브젝트가 단순히 텍스트를 통해서가 아니라 파이프라인을 통해서 진행된다는 것을 기억하라. 이는 파이프의 어떠한 시점에서도 세부적인 정보를 얻는 것이 가능하다는 것을 의미한다.

만약 윈도우즈의 cmd나 다른 유닉스 계열의 쉘 같이 다른 쉘을 이용해본 적이 있다면 텍스트를 출력하는 커맨드가 다른 커맨드로 내용을 전달 할 수 있다는 것을 알 것이다. 예를 들면 cmd와 DOS의 dir 커맨드는 파일 리스트를 출력한다. 이 리스트가 텍스트의 형태다. 단순히 dir을 입력하면 윈도우 콘솔 화면에서 파일 리스트를 보게 될 것이다. 그러나 리스트를 화면에 출력하는 대신에 다른 커맨드에 입력으로 넣을 수 있다. 이것을 파이핑 이라고 부른다. more 커맨드는 텍스트를 읽거나 한 페이지 분량씩 출력하고 대기 하다가 키 입력이 있으면 다음 페이지를 보여주는 기능을 한다.
C:\WINDOWS >dir /ad | more
 Volume in drive C has no label.
 Volume Serial Number is BCFB-2313

 Directory of C:\WINDOWS

11/04/2006  10:59 PM    <DIR>          .
11/04/2006  10:59 PM    <DIR>          ..
06/07/2004  07:03 PM    <DIR>          $NtUninstallKB824105$
06/07/2004  07:05 PM    <DIR>          $NtUninstallKB824141$
10/15/2004  09:06 PM    <DIR>          $NtUninstallKB824151$
06/07/2004  07:01 PM    <DIR>          $NtUninstallKB825119$
06/07/2004  07:00 PM    <DIR>          $NtUninstallKB828035$
06/07/2004  06:58 PM    <DIR>          $NtUninstallKB828741$
06/07/2004  06:59 PM    <DIR>          $NtUninstallKB833407$
-- More  --
사람들은 이러한 파이프가 텍스트를 다루는데 막강한 유틸리티 라는 것을 알게 되었다. 몇 년 전에 awk와 grep이 개발되었고 이를 이용해서 텍스트를 처리하게 되었다. (awk는 공백으로 구분되는 레코드 파일로부터 조건을 만족하는 결과를 쉽게 얻을 수 있다. grep은 텍스트에서 패턴을 만족하는 부분을 찾을 수 있으며 현재까지도 많이 사용된다) 현재에 이르러서는 Perl 같은 훨씬 강력한 텍스트 처리 언어를 사용한다.

DOS의 dir과 같이 간단한 커맨드가 텍스트를 이용하는 반면 보다 강력한 툴들은 오브젝트를 활용한다. 만약 윈도우즈 시스템에서 여러 개의 프로세스를 관리한다고 할 때 프로세스 하나는 텍스트 한 줄을 뜻하는 것은 아니다. 여기서 프로세스는 프로세스 ID나 보안 설정 값 등으로 구성된 하나의 오브젝트다. 이러한 것은 단순한 텍스트 이상의 것이다.

만약 어떤 툴이 여러 프로세스를 가져와서 그 정보를 단순한 텍스트로 다른 툴에게 넘긴다면 정보를 넘겨 받은 툴은 속은 것이다. 그 툴은 실제 오브젝트가 아닌 단순한 프로세스의 텍스트 기반 정보를 얻은 것이다.

더 좋은 방식은 간단하게 첫번째 툴이 두 번째 툴에게 실제 오브젝트를 전달(pipe)하는 것이다. 툴은 결국 텍스트를 출력하는 윈도우를 다루어야 하기 때문에 처음엔 문제인 것처럼 보일 수도 있다. 그렇지만 dir | more처럼 커맨드가 함께 동작하는 것을 생각해 보면 마지막으로 콘솔 윈도우에 출력되는 것은 단순한 출력 이상의 것이다. dir에서 more로 정보가 전달되는 것은 전혀 콘솔에 표시되지 않는다.

여기 예가 있다.
PS C:\WINDOWS> dir | sort LastWriteTime | more

    Directory: Microsoft.PowerShell.Core\FileSystem::C:\WINDOWS


Mode                LastWriteTime     Length Name
----                -------------     ------ ----
-a---          7/4/1995   1:33 PM      11776 Ckrfresh.exe
-a---         7/31/1995   5:44 PM     212480 PCDLIB32.DLL
-a---          5/3/1996  10:36 AM      18432 Setup_ck.dll
-ar--          5/3/1996  12:21 PM      27648 Setup_ck.exe
-a---         7/22/1998  12:29 AM         21 CS_SETUP.ini
-a---        10/29/1998   3:45 PM     306688 IsUninst.exe
-a---         1/12/1999  10:39 AM       6656 delttsul.exe
-a---         1/12/1999  10:40 AM      29184 rmud.exe
-a---         6/18/1999   4:49 PM     165888 Ckconfig.exe
-a---        11/10/1999   3:05 PM      86016 unvise32qt.exe
...
(dir은 Get-Children의 별칭이고 sort는 Sort-Object의 별칭이다. 그리고 more는 Out-Host -paging을 호출한다. 따라서 dir | sort LastWriteTime | more는 Get-Children | Sort-Object | Out-Host -Paging.을 줄인 것이다.)

예에서 보이는 목록은 디렉터리를 LastWriteTime 필드로 정렬하고 한 페이지씩 출력하고 있다. 하지만 오브젝트들은 파이프라인으로 전달 된 후 마지막엔 결국 텍스트로 바뀌었기 때문에 아래와 같이 입력해서 결과를 변수에 저장할 수 있다.
PS C:\WINDOWS> $a = dir | sort LastWriteTime
변수 $a는 지금 Sort-Object 커맨드의 결과를 담고 있는데 $a의 내용은 단순한 텍스트가 아니다. dir(Get-ChildItem) 커맨드는 FileInfo와 DirectoryInfo 오브젝트의 리스트를 리턴받아 sort (Sort-Object) 커맨드에 전달했다. 따라서 $a는 FileInfo와 DirectoryInfo 오브젝트의 리스트이다. 아래와 같이 대괄호를 이용해서 각각의 원소에 접근할 수 있다.
PS C:\WINDOWS> $a[0]

    Directory: Microsoft.PowerShell.Core\FileSystem::C:\WINDOWS

Mode                LastWriteTime     Length Name
----                -------------     ------ ----
-a---          7/4/1995   1:33 PM      11776 Ckrfresh.exe


PS C:\WINDOWS> $a[1]

    Directory: Microsoft.PowerShell.Core\FileSystem::C:\WINDOWS

Mode                LastWriteTime     Length Name
----                -------------     ------ ----
-a---         7/31/1995   5:44 PM     212480 PCDLIB32.DLL
다음 섹션에서 오브젝트의 멤버함수 호출에 대해서 더 자세히 다루겠다. 여기서는 GetType() 함수를 호출해서 해당 오브젝트(단순한 텍스트가 아닌)의 타입을 알아보자. 아래는 내가 변수 $a 의 타입을 알아본 것이다.
PS C:\WINDOWS> $a.GetType()

IsPublic IsSerial Name                BaseType
-------- -------- ----                --------
True     True     Object[]            System.Array
오브젝트 $a는 배열이다. 이제 첫번째 원소가 무엇인지 알아보자.
PS C:\WINDOWS> $a[0].GetType()

IsPublic IsSerial Name                BaseType
-------- -------- ----                --------
True     True     FileInfo            System.IO.FileSystemInfo
6. 오브젝트 활용하기

파이프를 통해 전달되는 오브젝트는 클래스가 형상화된 것이다. 여러분들은 오브젝트의 데이터와 함수를 활용할 수 있다.

커맨드의 리턴으로 받은 오브젝트를 포함해서 모든 오브젝트의 멤버를 이용할 수 있다는 것을 잊지 말아라. Get-Member 커맨드를 이용해서 오브젝트의 멤버를 알아낼 수 있다.
PS C:\Documents and Settings\Jeff> $a = "abc"
PS C:\Documents and Settings\Jeff> Get-Member -InputObject $a


   TypeName: System.String

Name             MemberType            Definition
----             ----------            ----------
Clone            Method                System.Object Clone()
CompareTo        Method                System.Int32 CompareTo(Object value),...
Contains         Method                System.Boolean Contains(String value)
CopyTo           Method                System.Void CopyTo(Int32 sourceIndex,...
EndsWith         Method                System.Boolean EndsWith(String value)...
...
특정 커맨드의 결과를 파이프로 Get-Member에 넘기면 Get-Member는 커맨드가 리턴한 오브젝트의 멤버 리스트를 보여줄 것이다. 같은 타입인 두 오브젝트가 넘겨지는 경우에는 Get-Member는 타입에 대한 멤버의 목록을 한번만 보여줄 것이다. 예를 들어 당신이 Get-Process 커맨드로 리턴 받은 오브젝트의 멤버에 대해서 알고싶다고 하자. 그러면 파이프로 Get-Member에게 아래와 같이 전달한다.
PS C:\Documents and Settings\Jeff> Get-Process | Get-Member


   TypeName: System.Diagnostics.Process

Name                           MemberType     Definition
----                           ----------     ----------
Handles                        AliasProperty  Handles = Handlecount
Name                           AliasProperty  Name = ProcessName
NPM                            AliasProperty  NPM = NonpagedSystemMemorySize
PM                             AliasProperty  PM = PagedMemorySize
VM                             AliasProperty  VM = VirtualMemorySize
WS                             AliasProperty  WS = WorkingSet
add_Disposed                   Method         System.Void add_Disposed(Event...
add_ErrorDataReceived          Method         System.Void add_ErrorDataRecei...
...
Where-Object 커맨드는 주로 파이프라인에서 사용되며 정의된 기준을 만족하는 오브젝트만을 통과시킨다. 필터링 기준을 정의하여 파이프라인을 통과한 오브젝트의 멤버에만 접근하게 된다.

이를테면 여기에 전체 출력을 보이지는 않았지만 Get-Process | Get-Member는 Get-Process의 결과로 VirtualMemorySize라는 멤버를 갖는 각각의 오브젝트를 보여준다. 만약 당신이 VirtualMemorySize가 100 MB (정확히는 104,857,600 bytes) 이상인 프로세스의 리스트를 보고싶다고 하자. 이런 경우 아래와 같이 할 수 있다.
PS C:\Documents and Settings\Jeff> Get-Process | Where-Object {$_.VirtualMemorySize -gt 104857600}

Handles  NPM(K)    PM(K)      WS(K) VM(M)   CPU(s)     Id ProcessName
-------  ------    -----      ----- -----   ------     -- -----------
    948      15    38928      52788   346    12.23    712 dexplore
    256      10    72624      81592   194   136.00   2664 firefox
    350      14    30948      44268   133     7.06   3576 OUTLOOK
    309       8    31928       6404   833   221.14    356 sqlservr
    334       9    22188      14784   817     0.53    852 sqlservr
   1598      91    18668      27404   142   156.75   1864 svchost
    356      24    15708      23740   169   201.47   1536 WINWORD
Where-Object 커맨드는 스크립트의 중괄호 안에 파라메터 값을 취한다. 그 스크립트는 파이프라인으로 넘겨받는 모든 오브젝트 대해 수행된다. 넘겨진 오브젝트 들은 변수 $_ 에 대입된다. 따라서 $_.VirtualMemorySize는 현재 파이프라인에 있는 오브젝트의 멤버 VirtualMemorySize를 가리킨다. -gt는 ~ 보다 크다는 비교 연산자다. 따라서 현재 오브젝트의 가상 메모리 크기가 100 MB보다 큰지 아래와 같이 테스트 할 수 있다.
Get-ChildItem | foreach { $_.Fullname }
지금까지 보았듯이 오브젝트의 멤버들에 익숙해져야 한다. 관련 내용은 온라인 도움말을 이용해서 찾아볼 수 있다. 온라인 도움말로 이동했으면 우선 시스템을 클릭하고 다시 스트링을 클릭하면 이제 스트링 클래스의 도움말 페이지에 도달해있을 것이다. 페이지의 하단부(왼쪽 창의 트리안)에 String Members라는 항목이 있다. 그 페이지는 스트링 클래스의 모든 멤버 리스트를 보여준다.

예를들면 EndsWith라는 멤버가 있다. 이 멤버는 스트링의 끝이 주어진 문자 집합의 문자로 끝나는지의 여부를 알려준다.

여기 예문이 있다.
PS C:\> $a = "This is a test"
PS C:\> $a.EndsWith("test")
True
PS C:\> $a.EndsWith("this")
False
PS C:\>
7. 출력 형식

다양한 Format-커맨드를 이용해서 출력 형식을 구미에 맞게 변경할 수 있다.

파워셀은 파이프라인을 통해서 오브젝트를 전달한다. 다만 화면출력을 해야 하는 경우에만 오브젝트의 텍스트 버전을 얻는다. Get-Process를 실행해서 나온 오브젝트의 멤버 목록을 본다면 출력되는 것 보다 많이 볼 수 있을 것이다. 어떤 멤버가 출력될까? 그 답은 시스템 설정에 있다. 파워쉘 디렉터리를 들여다 보면 dotnettypes.format.ps1xml라는 파일이 있다. 이 XML파일은 다양한 타입의 출력 형식을 정의한다. 디렉터리 내에는 각각의 타입을 정의하는 *.format.ps1xml의 형식의 파일이 몇 개 있다. 이것에 관해서는 여기서 더 배울 수 있다.

출력 형식을 설정하기 위해 파워쉘 유저는 FormatTable이라는 커맨드를 사용한다. 이 커맨드는 오브젝트의 파이브라인을 취하며, 형식이 정의되 있는 *.format.ps1xml 파일을 이용한다. 다음과 같이 세팅을 오버라이딩 하고 멤버를 선택해서 화면에 출력할 수 있다.
Get-Process | Format-Table Id, Name
  Id Name
  -- ----
2876 alg
 532 ApntEx
2044 Apoint
3448 calc
1824 CFSvcs
2176 cmd
3760 cmd
1640 Crypserv
1316 csrss
위의 결과는 기본 세팅을 무시하고 테이블의 ID와 Name 컬럼을 출력한 것이다.

파워셀에는 4개의 형식 커맨드가 있다.
  • Format-Custom
  • Format-List
  • Format-Table
  • Format-Wide
Get-Help 명령을 써서 각각의 명령에 대해 알아볼 수 있다.

8. 모든 것은 계층화 되어있다

파워쉘 드라이브는 단순히 파일 시스템 이상의 것이다. 레지스트리, 환경 그리고 다른 데이터에 드라이브로서 접근할 수 있다. 컴퓨터를 계층적으로 정의하는 것은 오래 전부터 나온 개념이다. 이를테면 유닉스는 하드웨어를 항상 계층형 파일시스템의 일부로 다뤄왔다. 유사하게 파워쉘은 컴퓨터의 다양한 부분을 드라이브로 다룬다. 아래와 같이 Get-PSDrive 커맨드를 사용하면 현재 어떠한 드라이브가 가능한지 볼 수 있다.
PS C:\Documents and Settings\Jeff> Get-PSDrive

Name       Provider      Root                       CurrentLocation
----       --------      ----                       ---------------
Alias      Alias
C          FileSystem    C:\                        Documents and Settings\Jeff
cert       Certificate   \
D          FileSystem    D:\
Env        Environment
Function   Function
HKCU       Registry      HKEY_CURRENT_USER
HKLM       Registry      HKEY_LOCAL_MACHINE
Variable   Variable
예를 들면 Alias는 별칭의 리스트를 의미하는 드라이브다. 아래와 같이 원하는 어느 드라이브로든 변경할 수 있다.
PS C:\WINDOWS\system32> cd alias:
PS Alias:\>
PS Alias:\> dir

CommandType     Name                  Definition
-----------     ----                  ----------
Alias           ac                    Add-Content
Alias           asnp                  Add-PSSnapin
Alias           clc                   Clear-Content
Alias           cli                   Clear-Item
Alias           clp                   Clear-ItemProperty
Alias           clv                   Clear-Variable
Alias: 드라이브는 하위 디렉터리를 지원하지 않지만 Registry 같은 경우에는 지원한다.
PS Alias:\> cd HKCU:
PS HKCU:\> dir

   Hive: Microsoft.PowerShell.Core\Registry::HKEY_CURRENT_USER

SKC  VC Name                           Property
---  -- ----                           --------
  2   0 AppEvents                      {}
  1   0 CLSID                          {}
  4  32 Console                        {ColorTable00, ColorTable01, ColorTab...
 24   1 Control Panel                  {Opened}
  0   8 Environment                    {BAKEFILE_PATHS, INCLUDE, LIB, PROMPT...
  0   1 HBA                            {Version}
  1   5 Identities                     {Identity Ordinal, Migrated5, Last Us...
  3   0 Keyboard Layout                {}
  0   0 Movie Magic Screenwriter       {}
 19   0 Movie Magic Screenwriter Vo... {}
  0   0 Network                        {}
  1   1 Note-It                        {(default)}
  4   1 Printers                       {DeviceOld}
  1   1 RemoteAccess                   {InternetProfile}
  1   7 S                              {AutodiscoveryFlags, DetectedInterfac...
100   1 Software                       {(default)}
  0   0 UNICODE Program Groups         {}
  2   0 Windows 3.1 Migration Status   {}
  1   0 Win_32                         {}
  0   1 SessionInformation             {ProgramCount}
  0   7 Volatile Environment           {LOGONSERVER, CLIENTNAME, SESSIONNAME...


PS HKCU:\> cd Software\Microsoft
PS HKCU:\Software\Microsoft> dir


   Hive: Microsoft.PowerShell.Core\Registry::HKEY_CURRENT_USER\Software\Microso
ft

SKC  VC Name                           Property
---  -- ----                           --------
  1   0 Active Setup                   {}
  3   0 ActiveMovie                    {}
  2   0 Advanced INF Setup             {}
  1   0 ASF Stream Descriptor File     {}
  1   0 Automap                        {}
  1   4 Broadband Networking           {StatusTimeout, InternetStatusTimeout...
  1   1 ClipArt Gallery                {UserAdded}
  0   5 Clipbook                       {WindowsClipBook Viewer, WindowsClipb...
  0   2 Clock                          {iFormat, {CCF5A555-D92E-457b-9235-2B...
DOS에서처럼 여기서도 파일명에 패턴을 쓸 수 있다.
PS HKCU:\Software\Microsoft> dir *windows*


   Hive: Microsoft.PowerShell.Core\Registry::HKEY_CURRENT_USER\Software\Microso
ft

SKC  VC Name                           Property
---  -- ----                           --------
  3   0 Windows                        {}
  0   1 Windows Genuine Advantage      {code}
  0   5 Windows Help                   {Maximized, Xl, Xr, Yd...}
  1   0 Windows Media                  {}
  1   0 Windows NT                     {}
  1   0 Windows Script                 {}
  1   0 Windows Script Host            {}
?는 문자 하나와 매칭된다. 예를 들면 abc? 는 abc로 시작하며 뒤에 문자 하나가 붙은 문자열과 매치된다. 대괄호를 써서 매치할 문자열을 정의할 수도 있다. abc[123]은 abc1, abc2, 그리고 abc3과 매치된다.

9. 흐름과 스크립트를 사용해라

파워셀은 강력하며 스크립트를 지원하는 언어다.

많은 커맨드가 스크립트를 파라메터로 취한다. Where-Object가 한 예이다. 이전에 아래 코드를 본적이 있을 것이다.
Get-Process | Where-Object {$_.VirtualMemorySize -gt 104857600}
For-Each 오브젝트는 리스트의 각각 아이템에 대하여 스크립트를 실행시킨다.

간단한 예제를 보자.
PS C:\WINDOWS\system32> 1..10 | foreach { $_ * 2 }
2
4
6
8
10
12
14
16
18
20
이것만으로는 별로 유용한 예제는 아닌 듯하다. 이러한 기법은 다양하게 응용될 수 있다. 이를테면 디렉터리 내의 첫번째 줄에 "#backup"이라는 문자열이 들어가는 모든 txt 파일을 C:\backups 디렉터리로 복사할 수 있다.

한번 해보자.
dir *.txt | foreach { if ((Get-Content $_ -totalCount 1) -eq "#backup") { copy $_ c:\backups } }
우선 dir 커맨드의 결과가 파이프를 통해서 foreach 커맨드로 보내진다. foreach 커맨드는 각 항목마다 중괄호로 쌓여진 스크립트를 실행한다. 이 스크립트는 각 파일의 첫번째 줄을 읽어서(Get-Content의 -totalCount 1 은 첫번째 줄만 허용) #backup과 비교한다. 만약 문자열이 맞으면 스크립트는 그 파일을 복사한다.

10. 개인 환경을 구축해라

profile.ps1 파일을 수정해서 각자의 입맛에 맞게 환경을 세팅 할 수 있다.

여러분들이 필요한 일을 수행하기 위해서 스크립트를 작성하고 나서는 나중을 위해서 그것을 보관하려고 할 것이다. 또한 기억하기 편하도록 명령어 몇 개에 별칭을 생성하고 싶어할 수 있다. 예를 들면 이전섹션에서 #backup이 들어가는 txt 파일을 저장하는 스크립트를 만들었다. 그것을 각자의 프로파일에 추가할 수 있다. 먼저 해당 스크립트는 아래와 같이 function 형식으로 만들어야 한다.
function Backup-TextFiles {
    dir *.txt | foreach {
        if ((Get-Content $_ -totalCount 1) -eq "#backup") { 
            copy $_ c:\backups } 
        }
    }
이 함수를 프로파일에 추가한다. 프로파일은 각자의 홈 디렉터리에 있는 Profile.ps1이라는 파일이다. 홈 디렉터리는 \Documents and Settings\\My Documents\WindowsPowerShell\profile.ps1이며, 은 각자의 실제 유저 이름이다.

하지만 스크립트를 실행하기 전에 보안 서명을 하는 절차가 있다. (이게 마음에 들지 않으면 보안 옵션을 해제할 수도 있다. 몇몇 블로그에서 이것에 대해서 말하지만 별로 좋은 생각은 아닌 듯 하다.) 이 링크는 각자가 작성한 스크립트에 서명하는 방법을 설명해 주는 괜찮은 곳이다. (기사에서 저자는 snap-in을 MMC에 추가하라고 언급했다. mmc.exe를 얻으려면 File->Add/Remove Snap-in을 클릭하라. makecert.exe를 확실히 동작시키려면, 저자가 말한 makecert.exe가 포함된 디렉터리에 위치해야 한다. 또한 변경 내용이 나오기 전에 MMC 윈도우를 리프레쉬 해야한다.)

결론

새로운 윈도우 파워쉘은 덩치가 크지만 거기에 압도될 필요는 없다. 내가 처음 파워쉘을 사용했을 때, 그것이 나의 인생을 이렇게 편하게 해주리라고는 상상도 못했었다. 너무 생소한 커맨드들이 즐비하고 하나 같이 타이핑 하기도 힘들게 길었다. 하지만 짧은 시간 안에 나는 커맨드와 별칭 그리고 파워쉘의 세상을 이해하는 공부를 시작했다. 마지막으로 이러한 툴을 제공해준 마이크로 소프트에 감사하며, 인생을 편안하게 해줄 파워쉘 관련 커뮤니티의 작품들을 볼 수 있을 것이라는 데 흥미를 느낀다. 파워쉘을 즐겨보자.

Jeff Cogswell는 신시내티 근방에 살며 15년간 소프트웨어 엔지니어로 일했다.
역자 김현우님은 알고리즘과 바이오인포메틱스 분야에 SCI 논문을 포함한 다수의 논문을 게재 하였으며, 정보과학회와 한국생명정보학회에서 우수논문발표상과 IBM Basic Research Award를 수상하였다. 현재는 LG전자에서 디지털 방송관련 어플리케이션을 개발하고 있다.
 
반응형

댓글