2013-02-16 3 views
1

확장자가 .xhtml 인 1000 개의 파일이 디렉토리 입력에 있고 해당 파일의 특정 하위 집합 (예 : $ (FILES)의 출력 경로 포함)이 필요하다고 가정합니다. xslt를 통해 디렉토리 출력에 같은 이름의 파일로 변환됩니다. 간단한 확인 규칙은 다음과 같습니다.gnu에서 하나의 명령으로 여러 파일에서 여러 파일 만들기 make

$(FILES): output/%.xhtml : input/%.xhtml 
    saxon s:$< o:[email protected] foo.xslt 

이는 물론 한 번에 하나씩 파일을 변환하는 방식으로 작동합니다. 문제는 내가 saxon의 일괄 처리를 사용하여 한 번에 모든 파일을 처리하기 때문에, 파일 수가 많을수록 각 파일에 대해 java 및 saxon을로드하는 오버 헤드를 고려하면 훨씬 빠를 것입니다. Saxon은 -s (source) 옵션을 디렉토리로 허용하고 그 디렉토리의 모든 파일을 처리하여 -o : 옵션에 지정된 디렉토리에 같은 이름으로 결과를 저장합니다.

output/%.xhtml: input/%.xhtml 
    saxon s:input -o:output foo.xslt 

하지만 내 경우에는이 두 가지 문제 앓고 :

나는 GNU 패턴 규칙을 사용하여 여러 파일을 업데이트하는 단일 명령을 할 수 있도록 얻을 잘 알려진 기술을 알고 있어요. 첫째, 변경된 파일뿐만 아니라 입력 디렉토리의 모든 파일에 대해 변환을 실행합니다. 둘째, 변환을 $ (FILES)에 지정된 파일의 서브 세트로 제한하지 않습니다. GNU는 일치 된 모든 타겟에 대해 패턴 규칙에 주어진 레서피를 실행하는 기능은 소위 "정적 패턴 규칙"([여기] 참조)의 경우에는 작동하지 않습니다. 게시물 알려져있다.

saxon 배치 기능을 사용하려면 임시 디렉토리를 만들어 처리 할 파일 만 복사 한 다음 해당 임시 디렉토리를 입력 디렉토리로 사용하여 변환을 실행해야합니다. 나는 임시 디렉토리를 생성했는데,

$(FILES): TMPDIR:=$(shell mktemp -d) 

를 사용하여, 향후 사용을 위해 목표 별 변수를 사용하여 이름을 기억하지만이 오래된있는 모든 단일 대상에 대한 새로운 임시 디렉토리를 작성합니다. 어쨌든 필자는 필요한 파일을 해당 디렉토리에 복사하는 규칙을 구성하는 방법을 잘 모릅니다. makefile을 파싱 할 때 임시 디렉토리를 생성하고 싶지 않습니다. 모든 재구성 파일을 구문 분석하여 현재 최상위 레벨 대상과 관련이없는 파일도 파싱 할 수 있습니다. 필요하지 않거나 사용하지 않을 상황에 대한 임시 디렉토리를 만들고자합니다.

단일 입력에서 여러 파일을 만드는 것에 대해 과거에 많은 질문이 제기되었음을 잘 알고 있습니다. 하나의 솔루션은 (비 정적) 패턴 규칙입니다. 다른 솔루션은 가짜 목표를 포함합니다. 그러나,이 경우에 나는이 모든 것을 함께 모으는 방법에 관해서 붙어 있습니다.

나는 하나이 복사 그들에게 반면 하나를 변경 파일을 식별하고 정적 패턴 규칙

$(FILES): output/%.xhtml : input/%.xhtml 
    TMPDIR=`mktemp -d` 
    cp $< $(TMPDIR) 

를 사용하여 복사 할 수 있지만 실제로 나는 하나의 cp 명령으로 파일을 복사하는 것을 선호 할 수 있습니다. 아마도 여기에 cp -u의 응용 프로그램이 있습니까?

업데이트가 필요한 파일에도 ad-hoc 확장 프로그램을 사용하는 것으로 생각했으나이를 작동시키는 방법을 알지 못했습니다. 나는 포기하고, saxon transform을 모든 파일에 적용 할 수 있습니다. 그러나 변경된 것이 있다면 더 좋은 방법이 있습니까?

답변

1

개인적으로 저는 명령 줄에서이 작업을 시도하지 않습니다. 내가 쉘 스크립팅 마법사가 아니기 때문에 그게 부분적입니다. 나는 앤트 마법사도 아니지만, 변경되지 않은 파일을 처리해야하기 때문에 이것은 앤트 영역에 많이 빠져있는 것 같습니다.반면에 Ant는 각 변환에 대한 스타일 시트를 다시 컴파일합니다. 이는 오버 헤드를 피할 수 있습니다. 그렇다면 자바 애플리케이션을 작성하는 것이 가장 좋습니다. 그것은 아마도 100 라인 또는 그 이하 일 것입니다.

최종 가능성은 Saxon 내에서 처리하는 것입니다. 즉, collection() 함수를 사용하여 여러 입력 파일을 읽고 xsl : result-document를 사용하여 여러 결과 파일을 생성하는 단일 변환입니다. Saxon (상용 버전)은 처리 할 파일을 필터링 할 수있는 마지막 수정 기능을 제공합니다. 1000 개의 파일을 사용하면 힙 채우기를 방지하기 위해 확장 기능 saxon : discard-document()를 원할 수 있습니다.

0

개인적으로 필자는 파일 당 원래 하나의 컴파일러를 선호합니다. make가 -j n 플래그로 잘 작동하지 않습니까?

물론 원본을 복사 한 다음 saxon을 실행하여 파일을 일괄 처리 할 수 ​​있습니다. Recursive make (우!)는 순서를 정렬 할 수 있습니다. 같은 뭔가 :

.PHONY: all 
all: 
    rm -rf tmpdir 
    ${MAKE} tmpdir/sentinel 
    saxon -s:tmpdir -o:output foo.xslt 

tmpdir/sentinel: $(FILES) ; touch [email protected] 

$(FILES): output/%.xhtml: input/%.xhtml 
    ln $< $(patsubst input/%,tmpdir/%,$<) 

이 작품은 내가하기 위해 거짓말을 매우 구역질이 나는 생각하지만, (정적 패턴 규칙은 output/에서 대상을 만들 취지 있지만, 사실 tmpdir/에 그 더러운 행위를하지) 않습니다.

tmpdir/sentinel의 제조법에 따르면 $?은 오래된 출력 파일 목록으로 올바르게 설정됩니다. 이것은 폴더가 아닌 saxon에 많은 파일을 전달할 수있는 경우 유용 할 수 있습니다.

0

'saxon'은 하나의 파일이나 디렉토리의 모든 파일을 지원하므로 임시 디렉토리에 복사하지 않고 일괄 처리에 적합하지 않습니다.

그렇지 않으면 타임 스탬프 마커 파일을 프록시 대상으로 사용하는 것이 매우 간단합니다. 예를 들어 :

output/.timestamp : $(FILES) 
    mkdir -p $(@D) 
    $(COMMAND) -outputdir=output $? 
    touch [email protected] 

세 가지 명령은 다음과 같습니다

  1. 출력 디렉토리가 있는지 확인하십시오.
  2. 타임 스탬프 파일보다 새로운 파일에 대해 배치 명령을 실행하십시오.
  3. 타임 스탬프 파일을 업데이트합니다 (필요한 경우 생성).

명령의 각 줄은 자체 서브 셸에서 실행되고 명령 줄에 오류가 있으면 이후 줄이 호출되지 않는다는 것을 기억하십시오.

이 방법은 Java 빌드에서 유용합니다.