PATCH(1)

명칭
patch - diff 파일을 오리지날의 파일에 적용한다

서식
patch [options] [origfile [patchfile]] [+ [options] [origfile]]...

그렇지만, 대부분은 이하와 같이 합니다.

patch <patchfile

해설
patch (은)는, diff 프로그램에 의해 생성된 4 개의 형식의 차분 정보를 포함한 패치 파일 (을)를 받아들여 오리지날 파일에 그 차분을 맞혀, 패치 끝난 바죠 를 생성합니다. 디폴트 동작에서는, 오리지날은 ".orig" 의 확장자(extension) (긴 파일명을 취급할 수 없는 시스템에서는 "~") (을)를 붙여 백업으로서 남긴 다음, 오리지날 파일은 패치 끝난 버젼으로 옮겨집니다. 오리지날을 백업 하는 확장자(extension)는 옵션 -b (--suffix), -B (--prefix) 혹은 -V (--version-control) 에 의해, 혹은 환경 변수 SIMPLE_BACKUP_SUFFIX 에 의해도 변경할 수 있습니다. 환경 변수에 의한 지정은 옵션지정에 의해 덧쓰기됩니다.

백업파일이 이미 존재하고 있었을 경우, patch (은)는 새로운 백업파일명으로서 파일명 본체 중(안)에서 최초로 나오는 영소문자의 부분을 대문자로 바꾼 것 (을)를 사용합니다. 영소문자의 부분이 없었던 경우는, 파일명의 최초의 1 캐릭터 삭제한 것으로 해, 기존의 백업파일명으로 합치하지 않게 될 때까지 이것을 반복합니다.

파일의 출력처는 -o (--output) 그리고 지정할 수가 있습니다만, 만약 거기에 이미 같은 파일명의 파일이 존재하고 있으면(자), 우선 백업이 만들어집니다.

patchfile 하지만 지정되지 않는 경우나 하이픈인 경우, 패치는 표준 입력으로부터 읽힙니다. -i 인수가 지정되었을 경우, 표준 입력대신에, 이것에 계속되는 파일명이 사용됩니다. -i 지시문은 1 번만 사용 가능합니다.

patch 하지만 최초로 실시하는 작업은, 차분 정보가 어떤 형식이나 판별하는 것입니다. 이것은, 옵션 -c (--context), -e (--ed), -n (--normal), -u (--unified) 에 의해 형식을 지정할 수도 있습니다. context diff (old-style, new-style, unified) 및 normal diff 은 patch 자신에 의해 패치를 맞힐 수 있습니다. ed diff (이었)였던 경우는, 파이프를 통해 단지 패치 파일을 에디터 ed 에 입력할 뿐입니다.

patch (은)는, 차분 정보의 전에 포함되는 쓰레기를 스킵 해, 차분을 적용해, 그리고 후에 포함되는 쓰레기를 스킵 하려고 합니다. 그러니까 차분 정보가 들어간 기사나 메세지등을 그대로 patch 에게 주어도, 잘 동작할 것입니다. 차분 전체가 일정량만 인덴트 되고 있어도, 그것을 고려 후 처리됩니다.

context diff 의 경우, 그리고 normal diff 의 경우도 얼마인가 들어맞읍니다만, patch (은)는 패치에 쓰여진 행 번호가 올바르지 않은 경우에 그것을 검지해, 각 hunk (패치의 각각의 단위)를 적용하는 올바른 장소를 찾아내려고 시도합니다. 우선 hunk 에 쓰여진 행 번호에 대해, 전회 hunk 를 적용했을 때에 이용한 오프셋(offset)를 가산 혹은 감산합니다. 그것이 올바른 장소가 아니면, patch (은)는 일정한 행수만큼 그 전후를 주사 해,hunk 의 문맥(context)에 매치 하는 행을 찾습니다. 제일 처음은, patch (은)는 문맥중의 모든 행이 일치하는 장소를 찾습니다. 일치하는 장소가 발견되지 않는 경우, 패치가 context diff 형식이며, 게다가 최대 애매도(maximum fuzz factor)가 1 이상으로 설정되어 있으면, 문맥의 최초와 마지막 행을 무시해 재차 주사를 실시합니다. 그런데도 발견되지 않는 경우, 최대 애매도가 2 이상이라면, 문맥의 최초와 마지막 2 행을 무시해 재차 주사 합니다. (디폴트의 최대 애매도는 2 입니다) 만약 patch 하지만 패치를 맞히는 장소를 찾아낼 수 없었던 경우, 그 부분의 차분 정보를 리제크트파일에 출력합니다. 리제크트파일은, 통상, 출력 파일에 ".rej" 의 확장자(extension) (긴 파일명을 취급할 수 없는 시스템에서는 "#") (을)를 붙인 것이 됩니다. (주의: 입력 패치가 context diff 에서 만나도 normal diff 에서 만나도, 리제크트 부분은 context diff 형식에서 출력됩니다. 입력이 normal diff 의 경우, 문맥의 상당수는 단순한 null 이 됩니다. ) 이 리제크트파일에 출력될 때의 차분 정보에 붙일 수 있고 있는 행 번호는, 원래의 패치 파일에 있는 것과 다른 것이 되어 있을 가능성도 있습니다만, 원래의 것보다는 장소적으로 보다 가까운 위치가 되어 있다고 생각되는 행 번호가 됩니다.

패치의 각 hunk 이 처리될 때마다, 그 패치 처리가 성공한(succeeded)의 것인지 실패한(failed)의 것인지의 구별과 patch 하지만 추정한 패치 적용행 위치(새로운 파일에 있어서의 행 번호) 하지만 보고됩니다. 이 정도치가 차분중에 나타난 행 번호와 다른 경우, 그 엇갈림(오프셋(offset))도 보고됩니다. hunk 의 하나만이 큰 오프셋(offset)로 적용되었을 경우, 그것은 잘못한 위치에 적용된 것을 의미하는 「일지도」모릅니다. 또 패치 적용에 즈음하여 애매도(fuzz factor)가 이용되었을 경우도 그 취지 보고됩니다. 이 경우는 조금 의심해 보아야 하는이지요.

만약, 오리지날 파일이 명령행으로 지정되지 않았던 경우, patch (은)는, 에디트 해야 할 파일명을, 차분 정보의 전에 부가되고 있는 쓰레기안 (으)로부터 찾아내려고 합니다. context diff 의 헤더의 경우, 파일명은 "***" 혹은 "---" 으로 시작되는 행으로부터 찾아, 기존 파일에 일치하는 가장 짧은 이름이 이용됩니다. context diff에는 위와 같은 행이 포함됩니다만, 만약 헤더에 "Index:" 말하는 행이 있으면 patch (은)는 여기로부터 얻은 파일명을 사용하는 것을 시도합니다. context diff 헤더는 Index 행에 우선해 이용됩니다. 만약 파일명을 찾아낼 수가 없었던 경우, 패치 해야 할 파일명을 입력하도록 요구합니다.

만약 오리지날 파일이 발견되지 않는가 리드온리-이지만, SCCS 인가 RCS 파일이 존재하는 경우, patch (은)는 그 파일의 겟트 혹은 체크아웃을 시도합니다.

더해, 만약 차분의 전의 쓰레기안에 "Prereq: " 라고 하는 행이 포함되어 있으면, patch (은)는 그 행에 필요 조건 (통상은 버젼 번호) 가 써 있는 것으로 간주해 최초의 것 word 을 꺼내, 오리지날 파일안에 같은 word 이 있는지 어떤지를 조사합니다. 만약 그 word 를 발견할 수 없으면, patch (은)는 처리를 실행해도 좋은지, 확인을 요구하게 됩니다.

결국, 뉴스 리더를 사용하고 있을 때, 패치를 포함한 기사에 대해서

    | patch -d /usr/src/local/blurfl

(와)과 같이 지시해 주면,blurfl 디렉토리에 있는 파일에 기사로부터 직접 패치를 댈 수가 있는, 그렇다고 하는 것입니다.

패치 파일에,1 개이상의 패치가 포함되어 있었을 경우, patch (은)는, 각각이 다른 패치 파일인 것이라고 생각해 처리를 실행합니다. 이 경우, 패치를 맞혀야 할 오리지날 파일은, 지금까지 설명한 것처럼, 각각의 차분 정보중에서 추출할 수 있어 또, 각 차분 기술 전에 있는 쓰레기의 부분을 조사하는 것으로 파일명이나 리버젼 레벨등의 중요 사항을 얻을 수 있는, (와)과 가정하고 있습니다. 이 그 밖에,'+' 그리고 연결해 파일명을 늘어놓는 것으로, 2 번째 이후의 파일명을 지정할 수도 있습니다 (다만, 이 경우에서도, 패치 맞힌 후의 새로운 파일명을 지정할 수 없습니다).

patch 에는 다음과 같은 옵션이 있습니다:

-b suff, --suffix=suff
    ".orig" (이)나 "~" 대신에 suff 하지만 백업파일의 확장자(extension)로서 해석되도록(듯이) 합니다.

-B pref, --prefix=pref
    pref 하지만, 백업파일명의 전에 붙이는 프레픽스로서 해석되도록(듯이) 합니다. 이 지정을 실시하면 -b 의 지정은 무시됩니다.

-c, --context
    패치 파일을 context diff 형식으로서 해석합니다.

-C, --check
    어떤 처리를 하는지 확인합니다. 그러나 실행은 하지 않습니다.

-d dir, --directory=dir
    dir (을)를 디렉토리로 간주해, 처리 전에 그 디렉토리로 이동합니다.

-D sym, --ifdef=sym
    "#ifdef...#endif" 구조를 이용해 차분을 나타냅니다. 차분 정보를 바꾸는 심볼로서 sym 하지만 이용됩니다.

-e, --ed
    패치 파일을 ed 스크립트 형식으로서 해석합니다.

-E, --remove-empty-files
    패치 적용 후, 하늘의 파일은 삭제하도록(듯이) 합니다.

-f, --force
    유저는 처리 내용을 정확하게 파악하고 있는 것으로 간주해, patch (은)는 아무것도 묻지 않고, 다음과 같이 가정해 처리를 진행시킵니다. 즉, 패치 해야 할 오리지날 파일 찾아낼 수가 없었던 경우는 스킵 합니다. ``Prereq:'' 의 버젼이 올바르지 않아도, 패치를 실행합니다. 패치가 끝난 상태라고 생각되어도, 리버스 패치는 아니면 가정합니다. 덧붙여 이 옵션은, patch 하지만 표시하는 메세지를 억제하지 않습니다. 메세지를 멈추려면 -s (을)를 사용합니다.

-t, --batch
    -f (와)과 같습니다만, 다음과 같이 가정합니다. 패치 해야 할 오리지날 파일을 찾아낼 수가 없었던 경우는 스킵 합니다( -f (와)과 같다). ``Prereq:'' 의 버젼이 올바르지 않은 경우는, 스킵 합니다. 패치가 끝난 상태라고 생각되는 경우는, 리버스 패치와 가정합니다.

-F number, --fuzz=number
    최대 애매도를 설정합니다. 이 옵션은 context diff 형식에게만 적용되어 hunk 의 적용 위치를 찾을 때에 최대 number 행만 무시합니다. 이 값을 크게 하면(자) 패치가 잘못해 맞을 가능성도 증가하는 것에 주의해 주세요. 기본값은 2 이어, context 의 행수(통상은 3)보다 큰 값에는 하지 않습니다.

-i patchfile
    표준 입력대신에 patchfile 를 적용하도록, patch 에 지시합니다.

-I, --index-first
    patch 에,``Index:'' 행을 context diff 의 헤더보다 우선해 취급하게 합니다. PATCH_INDEX_FIRST 환경 변수를 설정하면 같은 효과를 얻을 수 있습니다.

-l, --ignore-whitespace
    패턴 매치의 조건을 느슨하게 해, 탭 및 공백에 관한 차이는 무시합니다. 패턴중이 연속하는 임의개의 공백은, 입력 파일중이 연속하는 임의개의 공백에 매치 합니다. 그러나 보통 캐릭터는 정확하게 합치하지 않으면 안됩니다. context 의 각 행에 대해서 입력 파일중에 매치 하는 행이 없으면 안됩니다.

-n, --normal
    패치 파일을 normal diff 형식으로서 해석합니다.

-N, --forward
    리버스 패치, 혹은 벌써 패치가 끝난 상태이다고 생각되는 패치를 스킵 합니다. -R 도 참조해 주세요.

-o file, --output=file
    file (을)를 출력 파일명이라고 해석합니다.

-p[number], --strip[=number]
    패스명의 제거 카운트(strip count)를 설정합니다. 패치 작성자와 다른 디렉토리에 파일을 두고 있는 경우, 패치 파일중의 패스명을 어떻게 해석하는지, 를 지시합니다. 제거 카운트는, 패스명의 선두로부터 몇개의 slash를 제거하는지, (을)를 지정하는 것입니다(그 사이에 있는 디렉토리명도 제거됩니다). 예를 들면, 패치 파일중의 파일명이

        /u/howard/src/blurfl/blurfl.c

    에서 만났을 경우, -p 혹은 -p0 옵션을 지정하면(자), 패스명은 전혀 수정되지 않습니다. -p1 (을)를 지정하면(자), 최초의 slash가 없다

        u/howard/src/blurfl/blurfl.c

    되어, -p4 (을)를 지정하면(자)

        blurfl/blurfl.c

    , 그리고 -p (을)를 전혀 지정하지 않으면 "blurfl.c" 됩니다. 다만, 그 전의 패스(u/howard/src/blurfl)가 상대 패스로 해서 존재하는 경우는 별개로, 그 경우, 패스명 전체는 무수정인 채입니다. 마지막으로, 이렇게 해 얻을 수 있던 파일을, 커런트 디렉토리 혹은 -d 옵션으로 지정한 디렉토리내에서 찾습니다.

-r file, --reject-file=file
    file (을)를 리제크트파일뼹으로서 해석합니다.

-R, --reverse
    이 패치가 신구 2 개의 파일을 바꿔 넣어 작성한 것인 것을 patch 에 알립니다. (예, 가끔씩은 그런 것도 일어난다고 생각하고 있습니다. 인간은 그러한 것입니다. ) patch (은)는 각 hunk 을 적용하기 전에 신구를 바꿔 넣습니다. 리제크트파일은 교체 후의 형식에서 출력됩니다. -R 옵션은 ed 스크립트 형식의 차분에는 사용할 수 없습니다. 역조작의 순서를 만들어 내려면 정보가 부족하기 때문입니다.

    만약 패치중의 최초의 것 hunk 이 실패하면, patch (은)는 그것을 리버스 패치로 해 잘 적용할 수 있는지 어떤지 시험합니다. 만약 잘되면, -R 옵션을 세트 해 패치를 맞힙니까, 라고 묻습니다. 그렇게 하지 않는다고 대답하면, 패치는 통상 대로 적용되어 갑니다. (주: 패치가 normal diff 형식에서, 게다가 최초의 명령이 추가 (즉 본래는 삭제)이라고, 이 방법에서는 리버스 패치를 검출할 수 없습니다. 하늘의 문맥은 어디에라도 매치 하므로, 추가 조작은 항상 성공해 버린다 (으)로부터입니다. 다행히, 발견적으로는, 패치는 행을 삭제하는 것보다도 추가 혹은 수정하는 것이 대부분이기 (위해)때문에, normal diff 형식의 리버스 패치는 삭제로부터 시작되어 실패에 끝나는 것이 대부분입니다. )

-s, --silent, --quiet
    에러의 경우 이외, 조용하게 처리를 실시합니다.

-S, --skip
    패치 파일중의 이 패치를 무시해, 다음의 패치로부터 처리를 계속하도록(듯이) 지시합니다. 예를 들면

        patch -S + -S + <patchfile

    (와)과 지정하면(자),3 개의 패치 가운데,1 번째와 2 번째의 패치를 무시합니다.

-u, --unified
    패치 파일을 unified diff 형식 (unidiff) 으로서 해석합니다.

-v, --version
    patch 명령의 리버젼 헤더와 패치 레벨을 표시합니다.

-V method, --version-control=method
    백업파일명의 작성 방법으로서 method (을)를 이용합니다. 작성되는 백업의 타입은 환경 변수 VERSION_CONTROL 그렇지만 지정할 수 있습니다만, 이 옵션은 거기에 우선합니다. -B (은)는 이 옵션에 우선해, 백업파일을 만들 때에 항상 프레픽스가 이용되도록(듯이) 합니다. 환경 변수 VERSION_CONTROL 및 -V 옵션의 인수의 지정은,GNU Emacs 의 `version-control' 변수와 같습니다. 보다 알기 쉬운 동의어도 인식됩니다. 유효한 값은 이하와 같다(일의에 단축하는 것도 가능):

    `t' 또는 `numbered'
        항상 숫자를 붙인 백업파일을 만듭니다.

    `nil' 또는 `existing'
        벌써 숫자 첨부 백업파일이 존재하는 경우는, 숫자 첨부 백업을 실시해, 그 이외의 경우는, 단순한 백업을 실시합니다. 이것이 디폴트입니다.

    `never' 또는 `simple'
        항상 단순한 백업을 실시합니다.

-x number, --debug=number
    내부의 디버그 플래그에 값을 설정합니다. patch 명령에 패치를 대는 사람인 만큼 관계하는 것입니다.

저자
Larry Wall <lwall@netlabs.com>
및 많은 공헌자의 분들.

환경 변수

TMPDIR
    임시 파일을 두는 디렉토리. 디폴트에서는 /tmp

SIMPLE_BACKUP_SUFFIX
    백업파일에 붙이는 확장자(extension)를 지정합니다. 디폴트에서는, ".orig" 혹은 "~".

VERSION_CONTROL
    숫자 첨부 백업파일이 작성될 때에 선택합니다.

관련 파일
$TMPDIR/patch*

관련 항목
diff(1)

패치 작성자에게로의 주의
패치를 만들어 송부하려고 할 때에 유의해야 할 점이 몇개인가 있습니다. 제 1 에, patchlevel.h 라고 하는 파일을 관리하는 것으로 모두는 몹시 행복하게 될 수 있습니다. 작성한 패치 파일의 최초의 차분은 이 patchlevel.h 에 패치를 대어 패치 레벨을 인크리먼트(increment) 합니다. 패치안에 Prereq: 행을 넣어 두면, 차례 대로에 패치를 적용하지 않는 한 경고가 나옵니다. 제 2 에, context diff 헤더나 Index: 행으로 올바르게 파일명을 지정해 있다 것을 확인해 주세요. 서브 디렉토리에 있는 파일에 패치를 대려고 하는 경우는, 필요에 따라서 -p 옵션을 지정하도록, 유저에게 전해 주세요. 제 3 에, 하늘의 파일과 신규 파일을 비교하는 차분을 송부하는 것으로, 새로운 파일을 생성할 수가 있습니다. 이것은, 타겟 디렉토리에 그 신파일이 아직 존재하지 않는 경우에게만 유효합니다. 제 4 에, 리버스 패치를 송부하지 않게 조심해 주세요. 그 패치는 적용제인가와 모두가 혼란합니다. 제 5 에, 예를 들면 582 개의 차분을 단 하나의 파일에 돌진해 하이사요나라로 할 수도 있을 수 있습니다만, 무엇인가 발광할 것 같게 되었을 때에 갖추어, 관계 있는 패치를 몇개의 독립한 파일에 정리하는 편이 아마 현명하겠지요.

진단
여기에 열거 다 할 수 없을 정도(수록) 많이 있습니다만, 일반적으로 patch 하지만 패치 파일을 해석할 수 없는 것을 나타내고 있습니다.

메세지 "Hmm..." 는, 패치 파일중에 처리할 수 없는 텍스트가 존재하고 있는 것, 그리고 patch (은)는 그 텍스트중에 패치가 있는지 어떤지, 만약 존재하면 어떤 형식의 패치인지를 추측하려고 하고 있는 것을 가리키고 있습니다.

하나에서도 리제크트파일이 작성되면, patch (은)는 제로가 아닌 종료 스테이터스로 종료합니다. 얼마든지의 패치를 반복해 적용하는 경우는, 이 종료 스테이터스를 체크해, 패치가 부분적 밖에 적용되지 않은 파일에 대해서 새로운 패치를 수신자명 이상하게 해야 합니다.

경고
patch 하 ed 스크립트 형식에서는 행 번호의 엇갈림을 나타낼 수 없습니다. 또 normal diff 형식에서도, 행 번호의 잘못을 지적할 수 있는 것은 "change" 명령나 "delete" 커멘드가 나타나는 경우만입니다. context diff 형식에서 애매도 3 을 지정했을 경우도 같은 문제가 있습니다. 적절한 대화 인터페이스가 추가될 때까지는, 이런 경우는 context diff 를 보고 비교해 수정이 의미적으로 올바른지 어떤지 확인해야 하겠지요. 물론, 에러 없게 컴파일 할 수 있으면, 패치는 잘 적용되었다고 하는 작은 싸인으로는 됩니다만, 반드시 언제나 그렇다고 하는 것은 아닙니다.

비록 많은 유추를 실시하지 않으면 안 되는 경우에서도, patch (은)는 통상, 올바른 결과를 생성합니다. 그러나, 결과가 올바르면 프로텍션할 수 있는 것은, 패치를 작성한 것과 정확하게 같은 버젼의 파일에 대해서 패치를 적용했을 경우만입니다.

버그
좀 많은 deviant 오프셋(offset)와 교체 코드에 의해, 부분적인 매칭에 관해서 더욱 영리하게 할 수 있습니다만, 그러기 위해서는 패스를 추가할 필요가 있을 듯 합니다.

코드가 복제되고 있는 경우(예를 들면 #ifdef OLDCODE ... #else ... #endif 에 따라서), patch (은)는 양자에게 패치를 댈 수가 없습니다. 그리고 거기서 패치 명령이 잘되었을 경우, 그 패치는 아마 잘못해 적용되고 있어 게다가 「성공했습니다」라고 보고해 옵니다.

이미 적용제의 패치를 대면(자), patch (은)는 그것을 리버스 패치라고 생각해 적용한 패치를 제외하는지 어떤지 물어 옵니다. 이것도 특징의 하나로 해석 가능하겠지요.