공백이있는 경로에서 $ (dir) 또는 $ (notdir) 사용
문제
MakeFile에서 다음과 비슷한 코드를 사용하고 있습니다.
empty:=
space:= $(empty) $(empty)
path_escape = $(subst $(space),\$(space),$(1))
TOP=$(call path_escape,$(abspath .))
TARGET=$(TOP)/foo
$(info TOP='$(TOP)')
$(info TARGET='$(TARGET)')
all: $(TARGET)
$(TARGET):
touch '$(notdir $@)'
.PHONY: $(TARGET)
공간이없는 디렉토리에서 이것을 사용하면 space-test
, 그것은 잘 작동합니다 :
$ make
TOP='/tmp/space-test'
TARGET='/tmp/space-test/foo'
touch 'foo'
그러나 공백이있는 디렉토리에서 사용하면 space test
, 그 다음에 $(notdir)
잘못된 일을합니다.
TOP='/tmp/space\ test'
TARGET='/tmp/space\ test/foo'
touch 'space foo'
여기서 일어나는 일은 그 것입니다 $(notdir)
해석 /tmp/space test/foo
~처럼 둘 경로와 "파일 부분"을 반환합니다 둘 다 (즉, space
그리고 foo
). 이것의 이상한 부분은 그 것입니다 TARGET
제대로 탈출됩니다. 어떻게 든, 규칙 내부 또는 내부 $(notdir)
, 백 슬래시 탈출은 무시되고 있습니다.
여기서 내가 뭘 잘못하고 있니?
해결책
그만큼 $(notdir)
GNU의 기능은 공백으로 분리 된 인수 목록을 가져옵니다. 일부 기능은 탈출 공간을 지원합니다 \\
, 하지만 $(notdir)
그들 중 하나가 아닙니다.
이것은 작동해야합니다 :
s? = $(subst $(empty) ,?,$1)
?s = $(subst ?, ,$1)
notdirx = $(call ?s,$(notdir $(call s?,$1)))
$(TARGET):
touch '$(call notdirx,$@)'
이것은 "공간 안전"버전을 정의합니다 notdir
~라고 불리는 notdirx
. 아주 간단합니다. s?
먼저 모든 공간을 물음표로 바꾸고 (파일 이름으로 표시 될 수 없기를 바랍니다). ?s
다시 변환합니다. 그 사이에서 우리는 원본을 안전하게 호출 할 수 있습니다 notdir
기능.
파일 이름의 GNU 제조업체 및 공백에 대한 훌륭한 요약은 GNU는 공백이있는 파일 이름을 충족시킵니다.
다른 팁
유닉스 쉘이 있다고 가정하면 다음을 수행 할 수 있습니다.
notdirx = $(shell basename '$1')
dirx = $(shell dirname '$1')
비슷한 전략이 다른 기능에 적용될 수 있습니다. 단일 인수로 취급하려는 공백에 감염된 텍스트가 포함 된 변수 주변의 견적 표시를 기억하십시오. 이것은 또한 다른 특수 캐릭터로부터 당신을 보호 할 것입니다 (견적 마크 제외!). 다음은 Wildcard Glob의 결과에서 모든 공간을 탈출하는 예입니다.
$(shell ls -1 '*.foo' | sed 's/ /\\\\ /g')
Windows는 이제 디렉토리 이름에 괄호를 넣고 있습니다. C:\Program Files (x86)\
아직 분명하지 않습니다. make
.
이것은 어둠 속에서 단지 샷입니다.
TOP='"/home/chris/src/tests/make/space test"'